it-swarm-eu.dev

SQL: Co zpomaluje VLOŽENÍ, pokud ne CPU nebo IO?

Máme databázi pro produkt, který je odolný proti zápisu. Právě jsme si koupili nový serverový stroj s SSD, abychom vám pomohli. K našemu překvapení nebyly vložky rychlejší než na našem starém stroji s mnohem pomalejším úložištěm. Během benchmarkingu jsme si všimli, že míra IO=) vykazovaná procesem SQL Server byla velmi nízká.

Například jsem spustil skript nalezený na tato stránka , kromě toho, že jsem přidal BEGIN TRAN a COMMIT kolem smyčky. V nejlepším případě jsem viděl využití disku dosáhnout 7Mb/s, zatímco CPU sotva dotkl 5%. Na serveru je nainstalován 64 Gb a používá 10. Celková doba běhu byla 2 minuty 15 sekund pro první volání až asi 1 minutu pro následující hovory. Databáze je na jednoduché zotavení a během testu byla nečinná. Mezi každým hovorem jsem upustil stůl.

Proč je takový jednoduchý skript tak pomalý? Hardware se sotva používá. Oba vyhrazené nástroje pro srovnávání disků a SQLIO naznačují, že SSD pracuje správně s rychlostmi nahoru 500 MB/s pro čtení i zápis. Chápu, že náhodné zápisy jsou pomalejší než sekvenční zápisy, ale očekával bych, že jednoduchá vložení, jako je tato, do tabulky bez skupinového indexování, bude mnohem rychlejší.

Nakonec je náš scénář mnohem složitější, ale mám pocit, že nejprve musím pochopit jednoduchý případ. Stručně řečeno, naše aplikace odstraní stará data, pak pomocí SqlBulkCopy zkopíruje nová data do pracovních tabulek, provede určité filtrování a nakonec použije MERGE a/nebo INSERT INTO v závislosti na případech pro zkopírování dat do konečných tabulek.

-> Úpravy 1: Sledoval jsem postup, který spojil Martin Smith, a dostal jsem následující výsledek:

[Wait Type]  [Wait Count] [Total Wait (ms)] [T. Resource Wait (ms)] [T. Signal Wait (ms)]
NETWORK_IO          5008              46735                 46587        148
LOGBUFFER           901               5994                  5977         17
PAGELATCH_UP        40                866                   865          1
SOS_SCHEDULER_YIELD 53279             219                   121          98
WRITELOG            5                 145                   145          0
PAGEIOLATCH_UP      4                 58                    58           0
LATCH_SH            5                 0                     0            0

Připadá mi to podivné, NETWORK_IO zabere většinu času, vezmeme-li v úvahu, že se nezobrazí žádný výsledek a žádná data se nepřenášejí nikde jinde než do SQL souborů. Zahrnuje typ NETWORK_IO všechny IO?

-> EDIT 2: Vytvořil jsem 20Gb RAM disk a odtud jsem připojil databázi. Nejlepší čas, který jsem měl na SSD, je 48s, s RAM) = disk to kleslo na 37 sekund. NETWORK_IO je stále největší čekání. Maximální rychlost zápisu na disk RAM disk byla asi 250Mb/s, zatímco je schopen dělat multi gigabajty za sekundu. Stále nepoužívali moc CPU, tak co drží SQL?

20
Djof

Vím, že je to stará otázka, ale to by stále mohlo pomoci pátračům a je to problém, který se objevuje každou chvíli.

Hlavním důvodem, proč zasáhnete výkonnostní strop, aniž byste viděli jakékoli překážky v prostředcích, je to, že jste dosáhli limitu toho, co je možné zpracovat v rámci jednoho vlákna jedné relace. Smyčka není zpracována paralelně, ale všechny vložky jsou prováděny sériově.

V mém případě vložení 3 milionů řádků trvá 36 sekund. To znamená 36/30000000 = 0,000012 sekund za řádek. To je docela rychlé. V mém systému stačí 0,000012, abych prošel všemi nezbytnými kroky.

Jediným způsobem, jak toho dosáhnout rychleji, je spuštění druhé relace paralelně.

Pokud začnu 2 relace paralelně, obě dělají 15 milionů příloh. Oba skončí za 18 sekund. Mohl bych škálovat více, ale moje současné nastavení testu zasáhlo 95% procesorů se dvěma paralelními relacemi, takže provedení 3 by šikmé výsledky, protože bych narazil na problémové místo CPU.

Pokud spustím 2 paralelní relace, které vloží 3 miliony řádků, oba skončí za 39 sekund. takže to je nyní 6 milionů řádků za 39 sekund.

Dobře, to nás stále nechá čekat, až se objeví NETWORK_IO.

Čekání NETWORK_IO přidává skutečnost, že je pomocí trasovaných událostí sledujete. V mém případě trvá vložení 36 sekund (v průměru). Při použití rozšířené události (z výše uvedeného odkazu v prvním komentáři) je to registrováno:

Wait Type             Wait Count  Total Wait Time (ms) Total Resource Wait Time (ms) Total Signal Wait Time (ms)
NETWORK_IO            3455        68808                68802                         6
PAGEIOLATCH_SH        3           64                   64                            0
PAGEIOLATCH_UP        12          58                   58                            0
WRITE_COMPLETION      8           15                   15                            0
WRITELOG              3           9                    9                             0
PAGELATCH_UP          2           4                    4                             0
SOS_SCHEDULER_YIELD   32277       1                    0                             1
IO_COMPLETION         8           0                    0                             0
LATCH_SH              3           0                    0                             0
LOGBUFFER             1           0                    0                             0

Vidíte, že je zaregistrováno 68 sekund NETWORK_IO. Ale protože vložená smyčka je jednovláknová akce, která trvala 36 sekund, nemůže to být. (Ano, používá se více vláken, ale operace jsou sériové, nikdy paralelně, takže nemůžete kumulovat více čekací doby, než je celková doba trvání dotazu)

Pokud nepoužívám rozšířené události, ale pouze čekací statistiky DMV v tiché instanci (pouze já spustím vložení), dostanu toto:

Wait Type                   Wait Count  Total Wait Time (ms)  Total Resource Wait Time (ms) Signal Resource Wait Time (ms)
SOS_SCHEDULER_YIELD             8873                 0.21                                    0.01                                    0.20
PAGEIOLATCH_UP                  3                    0.02                                    0.02                                    0.00
PREEMPTIVE_OS_AUTHENTICATIONOPS 17                   0.02                                    0.02                                    0.00
PAGEIOLATCH_SH                  1                    0.00                                    0.00                                    0.00

NETWORK_IO, které jste viděli v protokolu rozšířených událostí, tedy nesouviselo s vaší smyčkou vložení. (Pokud byste nezapnul nocount, měli byste masivní asynchronní síť IO čeká, +1 Martin)

Nevím však, proč se NETWORK_IO zobrazuje v rozšířeném trasování událostí. Zajistěte, aby se zápis do asynchronního cílového souboru událostí akumuloval ASYNC_NETWORK_IO, ale to vše se děje na odlišném SPID, než na kterém filtrujeme. Mohl bych si to položit jako novou otázku sám)

10
Edward Dortland

Obvykle začnete pohledem na sys.dm_exec_requests , konkrétně na wait_time, wait_type a wait_resource pro vaše INSERT žádosti. Tím se jasně uvede, co blokuje váš VLOŽIT. Výsledky naznačí, zda se jedná o zamčení zámku, události růstu souboru, vyčkávání logů, tvrzení o přidělení (projevuje se jako tvrzení o zablokování stránky PFS) atd. Atd. Atd. Jakmile změříte, odpovídajícím způsobem aktualizujte svou otázku. Důrazně vás žádám, abyste se zastavili a přečetli si metodologii odstraňování problémů Waits and Queues , než budete pokračovat.

9
Remus Rusanu

Testovací skript jsem spustil na stránce propojené v OP s BEGIN TRAN/COMMIT kolem smyčky. Na mém stroji trvalo poprvé 1:28.

Pak jsem tyto dva příkazy přesunul mimo smyčku:

SELECT @Random = ROUND(((@Upper - @Lower -1) * Rand() + @Lower), 0)
SET @InsertDate = DATEADD(dd, @Random, GETDATE())

Po 28 sekundách to skončilo.

Nevím s jistotou, co se děje, ale hádám, že v kódu Rand() může být nějaký spánek, možná jako součást algoritmu, který používají ke generování entropie (lépe náhodný) čísla).

FWIW, SSD nejsou vždy nejlepší technologií pro aplikace náročné na zápis. Chcete-li dosáhnout nejlepšího výkonu, ujistěte se, že váš protokol DB je na jiném písmenu jednotky než data DB, soubor protokolu je předem dospělý na svou maximální velikost a nikdy jej zkraťte.

3
RickNZ

Další DMV, které používám k identifikaci pomalosti, je sys.dm_os_waiting_tasks . Pokud váš dotaz není náročný na CPU, můžete najít další informace o čekacích lhůtách z tohoto DMV.

1
StanleyJohns

Zkontroluji seznam čekacích událostí na SQL 2008 a nevidím v seznamu NETWORK_IO: http://technet.Microsoft.com/en-us/library/ms179984 (v = sql.100). aspx

Myslel jsem, že NETWORK_IO byl právě uveden jako ASYNC_NETWORK_IO, takže jsem se chtěl zeptat, zda byste mohli znovu zkontrolovat verzi SQL, protože jsem prostě zvědavý, jak a proč se tato čekací událost u této verze objevuje.

Pokud jde o síťové čekání, které se objevuje vůbec, ano, k tomu může dojít, i když pracujete na samostatném serveru. Zkontrolovali jste nastavení síťových karet? Zajímalo by mě, jestli jsou problémem.

Na konci dne je možné jen několik úzkých míst zdrojů: paměť, CPU, disk I/O, síť a uzamčení. Uvedli jste, že CPU a I/O nejsou problémem, a máte čekací událost NETWORK_IO, takže navrhuji, abyste se nejprve podívali na tyto karty NIC).

0
SQLRockstar