SQL: Testowanie dysku pod SQL: diskspd (Disk speed)

6-wrz-2018

Czasami instalujemy SQL na tym co mamy. Pojawił się serwer i ktoś oczekuje, że zainstalujesz na nim silnik bazy danych. Istalujesz i już. Czasami jednak i na szczęście zdarza się to coraz częściej klient jest zainteresowany nie tylko zainstalowaniem serwera ale i jego wydajnością. Kluczowym parametrem determinującym pracę serwera jest prędkość dysków. Chyba dla każdego dysku da się tak zbudować test, w którym ten dysk wypada najlepiej i… to jest pewnie to, co robią producenci. Nam, administratorom, zależy jednak raczej na empirycznym i dość obiektywnym sptawdzeniu wydajności systemu dyskowego.

Jednym z programów, który może dla nas taką wstępną analizę przeprowadzić jest Disk Speed – https://gallery.technet.microsoft.com/DiskSpd-A-Robust-Storage-6ef84e62

Programu nie trzeba instalować – to wielka zaleta, bo instalacja programu na systemie produkcyjnym to czynność, którą ty – administrator bazy – być może musiałbyś uzgodnić z administratorem systemu operacyjnego. Program dostępny po prostu w postaci pliku exe jest wiec w tej sytuacji wygodniejszy.

Zaraz dokładniej omówię parametry, ale zrobimy to na przykładzie konkretnego testu:

.\diskspd.exe -b64K -d30 -t8 -o8 -h -r -w20 -L -c2G test_002.dat> diskspeed_report.txt

-b64K – oznacza rozmiar bloków w jakich są wykonywane operacje. Ponieaż zalecany rozmiar dysku dla SQL to 64 KB (rozmiar extentu = 8 * 8 KB) to wybór tej wartości przy testowaniu dysku pod SQL jest trafny

-d60 – oznacza duration, czyli czas trwania testu. Kiedy testujesz „na serio” to wydłużenie tego czasu wydaje się sensowne. Ja nie chcę tu spędzać zbyt wiele czasu, więc ograniczam test do minuty. Domyślny czas, kiedy opuścisz tą opcję to 10 sek. Czas niby nie ma konkretnego znaczenia. Jeśli jednak (choć należy tego uniknąć) na systemie dzieją się inne rzeczy, to długi czas testu pozwala na lepiej uśrednione rezultaty.

-08 – oznacza „outstanding requests”. Kiedy dysk pod SQL jest bardzo obciążony, procesy ustawiają sie w kolejce. Ta kolejka do dysku powinna być krótka. Wartość 8 oznacza, że sztucznie generujemy długą kolejkę do dysku, mamy więc pewność że dyski nie będą się nudzić.

-t8 – oznacza ilość wątków (thread). Popatrz na to, ile rdzeni CPU (core) będzie pracować na rzecz SQL. W moim systemie mam 8 core, ale gdyby mój SQL miał korzystać np tylko z 4, wartość należałoby poprawić.  Łatwo obserwować działanie tej opcji zmieniając wartość parametru i patrząc na użycie procesorów.

-h – normalnie podczas pracy dysku są dodatkowo wykorzystywane „przyśpieszacze”. Wykorzystywane jest buforowanie softwarowe i/lub hardware’owe. Opcja h wyłącza ten mechanizm dokładnie tak samo jak robi to SQL. SQL chce mieć pewność, że dane są na dysku, a nie w buforze, który można utracić. Tak samo robi test z opcją h. Kiedy korzystasz z opcji -h zobaczysz mocne obciążenie dysku, a jeśli nie skorzystasz z tej opcji to obciążenie dysku nie będzie stałe, ale mocniej będą pracować inne komponenty jak CPU

-r – określa, że testowany ma być „random read”. Jeśli ta opcja nie jest włączona to testowany jest odczyt sekwencyjny. Tu przyda się Twoja wiedza o systemie. Jeśli chcesz na nim ustawić bazy OLTP skorzystaj z opcji -r. Jeśli na systemie będzie instalowana hurtownia, to może lepiej tej opcji nie stosować.

-w20 – jeśli nie skorzystasz z tej opcji, to testowany będzie tylko odczyt danych. Ale zazwyczaj baza nie tylko czyta dane ale i pisze. I znowu liczy się to co wiesz o Twoim systemie. Ja w tym teście zakładam, że 20% operacji to zapisy, a pozostałe 80% to odczyty. Jeśli u Ciebie spodziewane proporcje są inne, zmień ten parametr

-L – omawiane polecenie mierzy różne parametry dysku. Jednym z istotniejszych dla SQL jest Latency, które domyślnie nie jest dołączane do wyników.

-c2G – określa wielkość pliku na jakim można przeprowadić test. Tutaj mowa jest o utworzeniu pliku o rozmiarze 2GB. Na dyskach HDD mały plik będzie miał zazwyczaj dobrą wydajność, bo głowica dyskowa nie musi wiele wędrować aby odczytać dane. W takim przypadku pomyśl o testowaniu na większym dysku.

Wynik można oczywiście oglądać na ekranie, ale lepiej zachować go w pliku i za to sdpowiada  przekierowanie wyniku > results.txt

No i teraz najciekawsze – czyli odczyt wyników. Na początku wygenerowanego pliku znajdują się informacje o wykorzystanych parametrach. Całkiem to sensowne, bo kiedy przeprowadzisz wiele testów, to każdy z nich automatycznie będzie dobrze opisany.

Command Line: .\diskspd.exe -c2G -b64K -d30 -t8 -o8 -h -r -w20 -L test_001.dat

Input parameters:

timespan: 1
 -------------
 duration: 30s
 warm up time: 5s
 cool down time: 0s
 measuring latency
 random seed: 0
 path: 'test_001.dat'
 think time: 0ms
 burst size: 0
 software cache disabled
 hardware write cache disabled, writethrough on
 performing mix test (read/write ratio: 80/20)
 block size: 65536
 using random I/O (alignment: 65536)
 number of outstanding I/O operations: 8
 thread stride size: 0
 threads per file: 8
 using I/O Completion Ports
 IO priority: normal

Następna część to już wyniki testu z podziałem na poszczególne wątki – w tym przykładzie CPU. Wszystkie prezentowane zestawienia pozwalają zaobserwować szczegółowe obserwacje dla poszczególnych wątków, ale zawierają też jeden sumaryczny wiersz. Przy szybkiej analizie ten uśredniony wiersz powinien wystarczyć, ale kiedy chcesz zobaczyć dane na głębszym poziomie – masz taką możliwość:

  • zaczynamy od opisu obciążenia CPU. Chociaż diskspd przeprowadza analizę dysku, to wiedza o wykorzystaniu CPU jest równie cenna.
Results for timespan 1:
*******************************************************************************

actual test time: 30.00s
thread count: 8
proc count: 8

CPU | Usage | User | Kernel | Idle
-------------------------------------------
 0| 13.59%| 1.30%| 12.29%| 86.41%
 1| 3.07%| 0.52%| 2.55%| 96.93%
 2| 4.79%| 0.89%| 3.91%| 95.21%
 3| 3.85%| 0.63%| 3.23%| 96.15%
 4| 2.13%| 0.47%| 1.67%| 97.87%
 5| 2.50%| 0.62%| 1.87%| 97.50%
 6| 3.70%| 0.62%| 3.07%| 96.30%
 7| 4.84%| 1.20%| 3.64%| 95.16%
-------------------------------------------
avg.| 4.81%| 0.78%| 4.03%| 95.19%

Total IO
thread | bytes | I/Os | MiB/s | I/O per s | AvgLat | LatStdDev | file
-----------------------------------------------------------------------------------------------------
 0 | 1758330880 | 26830 | 55.89 | 894.22 | 8.944 | 12.183 | test_002.dat (2048MiB)
 1 | 1763377152 | 26907 | 56.05 | 896.78 | 8.919 | 12.228 | test_002.dat (2048MiB)
 2 | 1766916096 | 26961 | 56.16 | 898.58 | 8.900 | 12.048 | test_002.dat (2048MiB)
 3 | 1769144320 | 26995 | 56.23 | 899.71 | 8.889 | 12.033 | test_002.dat (2048MiB)
 4 | 1759838208 | 26853 | 55.94 | 894.98 | 8.937 | 12.040 | test_002.dat (2048MiB)
 5 | 1764163584 | 26919 | 56.07 | 897.18 | 8.914 | 12.181 | test_002.dat (2048MiB)
 6 | 1765539840 | 26940 | 56.12 | 897.88 | 8.906 | 11.773 | test_002.dat (2048MiB)
 7 | 1765736448 | 26943 | 56.12 | 897.98 | 8.906 | 12.047 | test_002.dat (2048MiB)
-----------------------------------------------------------------------------------------------------
total: 14113046528 | 215348 | 448.58 | 7177.32 | 8.914 | 12.067

Read IO
thread | bytes | I/Os | MiB/s | I/O per s | AvgLat | LatStdDev | file
-----------------------------------------------------------------------------------------------------
 0 | 1409613824 | 21509 | 44.80 | 716.87 | 8.100 | 11.084 | test_002.dat (2048MiB)
 1 | 1403518976 | 21416 | 44.61 | 713.77 | 7.965 | 10.153 | test_002.dat (2048MiB)
 2 | 1414922240 | 21590 | 44.97 | 719.57 | 8.094 | 11.408 | test_002.dat (2048MiB)
 3 | 1412562944 | 21554 | 44.90 | 718.37 | 8.063 | 11.132 | test_002.dat (2048MiB)
 4 | 1401094144 | 21379 | 44.53 | 712.54 | 8.110 | 11.462 | test_002.dat (2048MiB)
 5 | 1406599168 | 21463 | 44.71 | 715.34 | 8.092 | 11.575 | test_002.dat (2048MiB)
 6 | 1406468096 | 21461 | 44.70 | 715.27 | 8.051 | 10.921 | test_002.dat (2048MiB)
 7 | 1409024000 | 21500 | 44.79 | 716.57 | 8.119 | 11.670 | test_002.dat (2048MiB)
-----------------------------------------------------------------------------------------------------
total: 11263803392 | 171872 | 358.02 | 5728.31 | 8.074 | 11.186

Write IO
thread | bytes | I/Os | MiB/s | I/O per s | AvgLat | LatStdDev | file
-----------------------------------------------------------------------------------------------------
 0 | 348717056 | 5321 | 11.08 | 177.34 | 12.355 | 15.402 | test_002.dat (2048MiB)
 1 | 359858176 | 5491 | 11.44 | 183.01 | 12.639 | 17.699 | test_002.dat (2048MiB)
 2 | 351993856 | 5371 | 11.19 | 179.01 | 12.141 | 13.871 | test_002.dat (2048MiB)
 3 | 356581376 | 5441 | 11.33 | 181.34 | 12.160 | 14.630 | test_002.dat (2048MiB)
 4 | 358744064 | 5474 | 11.40 | 182.44 | 12.168 | 13.596 | test_002.dat (2048MiB)
 5 | 357564416 | 5456 | 11.37 | 181.84 | 12.149 | 13.851 | test_002.dat (2048MiB)
 6 | 359071744 | 5479 | 11.41 | 182.61 | 12.256 | 14.152 | test_002.dat (2048MiB)
 7 | 356712448 | 5443 | 11.34 | 181.41 | 12.014 | 12.977 | test_002.dat (2048MiB)
-----------------------------------------------------------------------------------------------------
total: 2849243136 | 43476 | 90.56 | 1449.01 | 12.235 | 14.590

total:
 %-ile | Read (ms) | Write (ms) | Total (ms)
----------------------------------------------
 min | 0.230 | 1.784 | 0.230
 25th | 6.455 | 8.476 | 6.673
 50th | 7.200 | 10.774 | 7.446
 75th | 7.767 | 13.235 | 8.271
 90th | 8.426 | 15.502 | 11.977
 95th | 9.611 | 17.254 | 14.355
 99th | 21.612 | 32.084 | 23.801
3-nines | 221.787 | 271.873 | 228.571
4-nines | 259.901 | 323.685 | 299.190
5-nines | 329.473 | 360.679 | 336.154
6-nines | 329.939 | 360.679 | 360.679
7-nines | 329.939 | 360.679 | 360.679
8-nines | 329.939 | 360.679 | 360.679
9-nines | 329.939 | 360.679 | 360.679
 max | 329.939 | 360.679 | 360.679

Informacje o dysku tak jak informacje o CPU są prezentowane z dokładnością do CPU jak i jeden dolny sumaryczny wiersz. Jedną z ważniejszych kolumn jest AvgLatency. Mówi się, że graniczną wartością jest 20ms, co oczywiście mocno zależy od tego, jak skonfigurowany jest podsystem dyskowy. Oczywiście im mniejsza wartość – tym lepiej! Inne informacje to:

  • bytes – ilość zapisanych/odczytanych bajtów z dysku
  • IOs – ilość operacji IO dla danego dysku. Każda z tych operachi dotyczy wartości wskazanej w parametrze b. U nas blok był 64-KB-ajtowy, więc ilość io należałoby pomnożyć przez wielkość bloku i w ten sposób  otrzymasz ilość przesłanych bajtów
  • MiB/s – ilość megabajtów na sekundę
  • I/O per s – ilość operacji na sekundę
  • AvgLat – średnie opóźnienie operacji dyskowej
  • LatStdDev – średnie odchylenie opóźnienia – pozwala stwierdzić jak bardzo od średniej odbiegają poszczególne operacje w porównaniu ze średnią

Jeżeli podzieliłeś operacje na odczyt i zapis, to znajdziesz jeszcze dodatkowo dwie osobne tabele opisujące osobno odczyt i zapis.

Wreszcie tabelka na samym dole opisuje opóźnienie dysku. Wprawdzie znajdziesz tam wiele wierszy, ale najważniejsze są pierwszy i ostatni. Pierwszy przedstawia minimalne opóźnienie – czyli idealną sytuację. Na systemie (i na podsystemie dyskowym) nie dzieje sie nic. Dysk jest gotowy do operacji i wtedy ty wysyłasz żądanie IO. To żądanie jest szybko obsługiwane. Ostatni wiersz przedstawia maksymalne opóźnienie. Na systemie (lub podsysstemie dyskowym) coś się dzieje. Wykonywane są inne operacje, a twoje polecenie musi poczekać. Takiego zachowania dysku można się spodziewać w peak-hours.

Mając takie narzędzie, możesz teraz porównać różne dyski i wybrać ten, który pasuje Ci najbardziej!

 

 

 

 

 

 

 

Komentarze są wyłączone

Autor: Rafał Kraik