sql >> Databáze >  >> RDS >> Database

Pohled na DBCC CHECKCONSTRAINTS a I/O

Běžným prvkem používaným při návrhu databáze je omezení. Omezení přicházejí v různých variantách (např. výchozí, jedinečné) a vynucují integritu sloupců, na kterých existují. Při správné implementaci jsou omezení mocnou součástí návrhu databáze, protože zabraňují tomu, aby se data, která nesplňují stanovená kritéria, dostala do databáze. Omezení však lze porušit pomocí příkazů jako WITH NOCHECK a IGNORE_CONSTRAINTS . Navíc při použití REPAIR_ALLOW_DATA_LOSS možnost s libovolnou DBCC CHECK příkaz k opravě poškození databáze, omezení se neberou v úvahu.

V důsledku toho je možné mít v databázi neplatná data – buď data, která nesplňují omezení, nebo data, která již neudržují očekávaný vztah primárního a cizího klíče. SQL Server obsahuje DBCC CHECKCONSTRAINTS k nalezení dat, která porušují omezení. Po provedení jakékoli možnosti opravy spusťte DBCC CHECKCONSTRAINTS pro celou databázi, aby se zajistilo, že neexistují žádné problémy, a mohou nastat situace, kdy je vhodné spustit CHECKCONSTRAINTS pro výběrové omezení nebo tabulku. Udržování integrity dat je zásadní, a přestože není obvyklé spouštět DBCC CHECKCONSTRAINTS na plánovaném základě najít neplatná data, když je potřebujete spustit, je dobré porozumět tomu, jaký dopad to může mít na výkon.

DBCC CHECKCONSTRAINTS lze spustit pro jediné omezení, tabulku nebo celou databázi. Stejně jako ostatní kontrolní příkazy může jeho dokončení trvat značnou dobu a spotřebovává systémové prostředky, zejména u větších databází. Na rozdíl od jiných kontrolních příkazů CHECKCONSTRAINTS nepoužívá snímek databáze.

Pomocí Extended Events můžeme zkoumat využití zdrojů, když spustíme DBCC CHECKCONSTRAINTS pro stůl. Abych lépe ukázal dopad, spustil jsem skript Create Enlarged AdventureWorks Tables.sql od Jonathana Kehayiase (blog | @SQLPoolBoy) k vytvoření větších tabulek. Jonathanův skript vytváří pouze indexy pro tabulky, takže k přidání několika vybraných omezení jsou nutné následující příkazy:

Použijte [AdventureWorks2012]; Go Alter Table [Prodej]. [SalesorderDetailenlarged] s kontrolou přidat omezení [fk_saleSorderDetailenlarged_SalesOrderheaderenlarged_saleSorderId] Cizí klíč ([SalesorderId]) [Prodej] [ProdesOrderheadeRedlaged] ([[SalesorderOrDid]) na detee casCetes; ZMĚNIT TABULKU [Prodej].[SalesOrderDetailEnlarged]SE ZKONTROLUJÍCÍ PŘIDAT OMEZENÍ [CK_SalesOrderDetailEnlarged_OrderQty]ZKONTROLUJTE (([OrderQty]>(0)))PŘEJÍT ALTER TABLE [Sales].[SalesOrder]WIDD WIDDROZŠŠÍŘENÝ_KONTROL[SalesOrderDetail]NITCHEDD ]>=(0,00)));PŘEJÍT ZMĚNIT TABULKU [Sales].[SalesOrderHeaderEnlarged]SE ZKONTROLUJTE PŘIDAT OMEZENÍ [CK_SalesOrderHeaderEnlarged_DueDate]ZKONTROLUJTE (([DueDate]>=[Datum objednávky]))PŘEDEJÍTE [SalesOrderHeader] ZKONTROLUJTE PŘIDAT OMEZENÍ [CK_SalesOrderHeaderEnlarged_Freight]ZKONTROLUJTE (([Freight]>=(0,00)))PŘEJÍT

Jaká omezení existují, můžeme ověřit pomocí sp_helpconstraint :

EXEC sp_helpconstraint '[Sales].[SalesOrderDetailEnlarged]';GO


sp_helpconstraint výstup

Jakmile budou existovat omezení, můžeme porovnat využití zdrojů pro DBCC CHECKCONSTRAINTS pro jediné omezení, tabulku a celou databázi pomocí Extended Events. Nejprve vytvoříme relaci, která jednoduše zachytí sp_statement_completed události, zahrnuje sql_text akci a odešle výstup do ring_buffer :

VYTVOŘTE RELACI UDÁLOSTI [Constraint_Performance] NA SERVERADD UDÁLOSTI sqlserver.sp_statement_completed( ACTION(sqlserver.database_id,sqlserver.sql_text))ADD CÍLOVÝ balíček0.ring_buffer( SET max_events003) EVLO7=EVLO_limit=TEN_TEN , MAX_DISPATCH_LATENCY=30 SECONDS, MAX_EVENT_SIZE=0 kB, MEMORY_PARTITION_MODE=NONE, TRACK_CAUSALITY=OFF, STARTUP_STATE=OFF);GO

Dále zahájíme relaci a spustíme každý z DBCC CHECKCONSTRAINT příkazy, poté vypište kruhovou vyrovnávací paměť do dočasné tabulky, abyste mohli manipulovat. Všimněte si, že DBCC DROPCLEANBUFFERS provede se před každou kontrolou, takže každá začne z chladné mezipaměti, přičemž se zachová pole pro testování úrovně.

ALTER EVENT SESSION [Constraint_Performance]ON SERVERSTATE=START;POUŽÍVEJTE [AdventureWorks2012];GO DBCC DROPCLEANBUFFERS;GODBCC CHECKCONSTRAINTS ('[Prodej].[CONSTRAINT_SalesOrderDetail]FFC . [Fk_salesorderdetailenlarged_salesorderheaderenlarged_salesorderid] ') s no_infomsgs; GodBCC DropCleanBuffers; GodBCC checkconstraints (' [SalesorderDetailenlarged] ') s no_informsg; SELECT @target_data =CAST(target_data AS XML) FROM sys.dm_xe_sessions AS s INNER JOIN sys.dm_xe_session_targets AS t ON t.event_session_address =s.[address] WHERE s.name =N'Constraint_Performance_Performance' AND N'tarfferget_name_t. '; SELECT n.value('(@name)[1]', 'varchar(50)') AS název_události, DATEADD(HOUR ,DATEDIFF(HOUR, SYSUTCDATETIME(), SYSDATETIME()),n.value('(@timestamp) )[1]', 'datetime2')) AS [časové razítko], n.value('(data[@name="duration"]/value)[1]', 'bigint') AS trvání, n.value( '(data[@name="physical_reads"]/value)[1]', 'bigint') AS fyzické_čtení, n.value('(data[@name="logic_reads"]/value)[1]', ' bigint') AS logical_reads, n.value('(action[@name="sql_text"]/value)[1]', 'varchar(max)') AS sql_text, n.value('(data[@name="statement"]/value)[1]', 'varchar(max)') AS [příkaz]DO #EventDataFROM @target_data.nodes('RingBufferTarget/event[@name=''sp_statement_completed'']') AS q( n);PŘEJÍT ZMĚNIT RELACI UDÁLOSTI [Constraint_Performance]NA SERVERSTATE=STOP;GO

Analýza ring_buffer do dočasné tabulky může nějakou dobu trvat (na mém počítači asi 20 sekund), ale opakované dotazování na data je rychlejší z dočasné tabulky než přes ring_buffer . Pokud se podíváme na výstup, vidíme, že pro každý DBCC CHECKCONSTRAINTS je provedeno několik příkazů :

SELECT *FROM #EventDataWHERE [sql_text] LIKE 'DBCC%';


Výstup rozšířených událostí

Použití Extended Events k prozkoumání vnitřního fungování CHECKCONSTRAINTS je zajímavý úkol, ale to, co nás opravdu zajímá, je spotřeba zdrojů – konkrétně I/O. Můžeme agregovat physical_reads pro každý kontrolní příkaz k porovnání I/O:

SELECT [sql_text], SUM([physical_reads]) AS [Total Reads]FROM #EventDataWHERE [sql_text] LIKE 'DBCC%'GROUP BY [sql_text];


Agregované I/O pro kontroly

Aby bylo možné zkontrolovat omezení, musí SQL Server přečíst data, aby našel všechny řádky, které by mohly omezení porušovat. Definice CK_SalesOrderDetailEnlarged_OrderQty omezení je [OrderQty] > 0 . Omezení cizího klíče, FK_SalesOrderDetailEnlarged_SalesOrderHeaderEnlarged_SalesOrderID , naváže vztah na SalesOrderID mezi [Sales].[SalesOrderHeaderEnlarged] a [Sales].[SalesOrderDetailEnlarged] tabulky. Intuitivně by se mohlo zdát, že kontrola omezení cizího klíče by vyžadovala více I/O, protože SQL Server musí číst data ze dvou tabulek. Nicméně [SalesOrderID] existuje na úrovni listu IX_SalesOrderHeaderEnlarged_SalesPersonID nonclustered index na [Sales].[SalesOrderHeaderEnlarged] tabulce a v IX_SalesOrderDetailEnlarged_ProductID index na [Sales].[SalesOrderDetailEnlarged] stůl. SQL Server jako takový prohledá tyto dva indexy, aby porovnal [SalesOrderID] hodnoty mezi dvěma tabulkami. To vyžaduje něco málo přes 19 000 přečtení. V případě CK_SalesOrderDetailEnlarged_OrderQty omezení, [OrderQty] sloupec není zahrnut v žádném indexu, takže dojde k úplnému prohledání seskupeného indexu, což vyžaduje více než 72 000 přečtení.

Když jsou zaškrtnuta všechna omezení pro tabulku, požadavky na vstup/výstup jsou vyšší, než když je kontrolováno jediné omezení, a znovu se zvýší, když se kontroluje celá databáze. Ve výše uvedeném příkladu [Sales].[SalesOrderHeaderEnlarged] a [Sales].[SalesOrderDetailEnlarged] tabulky jsou neúměrně větší než jiné tabulky v databázi. To není neobvyklé ve scénářích reálného světa; databáze mají velmi často několik velkých tabulek, které tvoří velkou část databáze. Při spuštění CHECKCONSTRAINTS u těchto tabulek si uvědomte potenciální spotřebu zdrojů potřebnou pro kontrolu. Pokud je to možné, provádějte kontroly mimo pracovní dobu, abyste minimalizovali dopad na uživatele. V případě, že kontroly musí probíhat během běžné pracovní doby, pochopení toho, jaká existují omezení a jaké existují indexy pro podporu ověřování, může pomoci změřit účinek kontroly. Nejprve můžete provést kontroly v testovacím nebo vývojovém prostředí, abyste pochopili dopad na výkon, ale poté mohou existovat odchylky na základě hardwaru, srovnatelných dat atd.  A nakonec nezapomeňte, že kdykoli spustíte kontrolní příkaz, který obsahuje REPAIR_ALLOW_DATA_LOSS možnost, pokračujte v opravě pomocí DBCC CHECKCONSTRAINTS . Oprava databáze nebere v úvahu žádná omezení, protože poškození je opraveno, takže kromě potenciální ztráty dat můžete skončit s daty, která porušují jedno nebo více omezení ve vaší databázi.


  1. Zvýšit pole databáze o 1

  2. Co dělat (nebo nedělat) s hlavními statistikami čekání

  3. jak vytvořit ISO-8601 gregoriánskou datovou tabulku v postgresu

  4. Získejte první den v měsíci v PostgreSQL