Database
 sql >> Teknologi Basis Data >  >> RDS >> Database

Melihat DBCC CHECKCONSTRAINTS dan I/O

Elemen umum yang digunakan dalam desain database adalah kendala. Kendala datang dalam berbagai rasa (misalnya default, unik) dan menegakkan integritas kolom tempat mereka ada. Ketika diimplementasikan dengan baik, kendala adalah komponen yang kuat dalam desain database karena mencegah data yang tidak memenuhi kriteria yang ditetapkan untuk masuk ke database. Namun, batasan dapat dilanggar menggunakan perintah seperti WITH NOCHECK dan IGNORE_CONSTRAINTS . Selain itu, saat menggunakan REPAIR_ALLOW_DATA_LOSS opsi dengan DBCC CHECK perintah untuk memperbaiki kerusakan basis data, batasan tidak dipertimbangkan.

Akibatnya, dimungkinkan untuk memiliki data yang tidak valid dalam database – baik data yang tidak mematuhi batasan, atau data yang tidak lagi mempertahankan hubungan kunci asing utama yang diharapkan. SQL Server menyertakan DBCC CHECKCONSTRAINTS pernyataan untuk menemukan data yang melanggar batasan. Setelah opsi perbaikan dijalankan, jalankan DBCC CHECKCONSTRAINTS untuk seluruh database untuk memastikan tidak ada masalah, dan mungkin ada saat-saat yang tepat untuk menjalankan CHECKCONSTRAINTS untuk batasan pilih atau tabel. Menjaga integritas data sangat penting, dan meskipun menjalankan DBCC CHECKCONSTRAINTS bukanlah hal yang biasa. secara terjadwal untuk menemukan data yang tidak valid, saat Anda perlu menjalankannya, sebaiknya pahami dampak kinerja yang mungkin ditimbulkannya.

DBCC CHECKCONSTRAINTS dapat mengeksekusi untuk satu kendala, tabel, atau seluruh database. Seperti perintah pemeriksaan lainnya, diperlukan waktu yang cukup lama untuk menyelesaikannya dan akan menghabiskan sumber daya sistem, terutama untuk database yang lebih besar. Tidak seperti perintah cek lainnya, CHECKCONSTRAINTS tidak menggunakan snapshot database.

Dengan Acara yang Diperpanjang, kita dapat memeriksa penggunaan sumber daya saat kita menjalankan DBCC CHECKCONSTRAINTS untuk meja. Untuk menunjukkan dampaknya dengan lebih baik, saya menjalankan skrip Create Enlarged AdventureWorks Tables.sql dari Jonathan Kehayias (blog | @SQLPoolBoy) untuk membuat tabel yang lebih besar. Skrip Jonathan hanya membuat indeks untuk tabel, jadi pernyataan di bawah ini diperlukan untuk menambahkan beberapa batasan yang dipilih:

USE [AdventureWorks2012];
GO
 
ALTER TABLE [Sales].[SalesOrderDetailEnlarged]
WITH CHECK ADD CONSTRAINT [FK_SalesOrderDetailEnlarged_SalesOrderHeaderEnlarged_SalesOrderID]
FOREIGN KEY([SalesOrderID])
REFERENCES [Sales].[SalesOrderHeaderEnlarged] ([SalesOrderID])
ON DELETE CASCADE;
GO
 
ALTER TABLE [Sales].[SalesOrderDetailEnlarged]
WITH CHECK ADD CONSTRAINT [CK_SalesOrderDetailEnlarged_OrderQty]
CHECK (([OrderQty]>(0)))
GO
 
ALTER TABLE [Sales].[SalesOrderDetailEnlarged]
WITH CHECK ADD CONSTRAINT [CK_SalesOrderDetailEnlarged_UnitPrice]
CHECK (([UnitPrice]>=(0.00)));
GO
 
ALTER TABLE [Sales].[SalesOrderHeaderEnlarged]
WITH CHECK ADD CONSTRAINT [CK_SalesOrderHeaderEnlarged_DueDate]
CHECK (([DueDate]>=[OrderDate]))
GO
 
ALTER TABLE [Sales].[SalesOrderHeaderEnlarged]
WITH CHECK ADD CONSTRAINT [CK_SalesOrderHeaderEnlarged_Freight]
CHECK (([Freight]>=(0.00)))
GO

Kami dapat memverifikasi kendala apa yang ada menggunakan sp_helpconstraint :

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


sp_helpconstraint keluaran

Setelah kendala ada, kita dapat membandingkan penggunaan sumber daya untuk DBCC CHECKCONSTRAINTS untuk satu kendala, tabel, dan seluruh database menggunakan Extended Events. Pertama kita akan membuat sesi yang hanya menangkap sp_statement_completed acara, termasuk sql_text tindakan, dan mengirimkan output ke ring_buffer :

CREATE EVENT SESSION [Constraint_Performance] ON SERVER
ADD EVENT sqlserver.sp_statement_completed
(
  ACTION(sqlserver.database_id,sqlserver.sql_text)
)
ADD TARGET package0.ring_buffer
(
  SET max_events_limit=(5000)
)
WITH 
(
    MAX_MEMORY=32768 KB, EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS,
    MAX_DISPATCH_LATENCY=30 SECONDS, MAX_EVENT_SIZE=0 KB,
    MEMORY_PARTITION_MODE=NONE, TRACK_CAUSALITY=OFF, STARTUP_STATE=OFF
);
GO

Selanjutnya kita akan memulai sesi dan menjalankan setiap DBCC CHECKCONSTRAINT perintah, lalu keluarkan buffer cincin ke tabel temp untuk dimanipulasi. Perhatikan bahwa DBCC DROPCLEANBUFFERS dijalankan sebelum setiap pemeriksaan sehingga masing-masing dimulai dari cache dingin, menjaga bidang pengujian level.

ALTER EVENT SESSION [Constraint_Performance]
ON SERVER
STATE=START;
GO
 
USE [AdventureWorks2012];
GO
 
DBCC DROPCLEANBUFFERS;
GO
DBCC CHECKCONSTRAINTS ('[Sales].[CK_SalesOrderDetailEnlarged_OrderQty]') WITH NO_INFOMSGS;
GO
DBCC DROPCLEANBUFFERS;
GO
DBCC CHECKCONSTRAINTS ('[Sales].[FK_SalesOrderDetailEnlarged_SalesOrderHeaderEnlarged_SalesOrderID]') WITH NO_INFOMSGS;
GO
DBCC DROPCLEANBUFFERS;
GO
DBCC CHECKCONSTRAINTS ('[Sales].[SalesOrderDetailEnlarged]') WITH NO_INFOMSGS;
GO
DBCC DROPCLEANBUFFERS;
GO
DBCC CHECKCONSTRAINTS WITH ALL_CONSTRAINTS, NO_INFOMSGS;
GO
 
DECLARE @target_data XML;
 
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'
  AND t.target_name = N'ring_buffer';
 
SELECT
  n.value('(@name)[1]', 'varchar(50)') AS event_name,
  DATEADD(HOUR ,DATEDIFF(HOUR, SYSUTCDATETIME(), SYSDATETIME()),n.value('(@timestamp)[1]', 'datetime2')) AS [timestamp],
  n.value('(data[@name="duration"]/value)[1]', 'bigint') AS duration,
  n.value('(data[@name="physical_reads"]/value)[1]', 'bigint') AS physical_reads,
  n.value('(data[@name="logical_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 [statement]
INTO #EventData
FROM @target_data.nodes('RingBufferTarget/event[@name=''sp_statement_completed'']') AS q(n);
GO
 
ALTER EVENT SESSION [Constraint_Performance]
ON SERVER
STATE=STOP;
GO

Mengurai ring_buffer ke dalam tabel temp mungkin memerlukan waktu tambahan (sekitar 20 detik di mesin saya), tetapi kueri data yang berulang lebih cepat dari tabel temp daripada melalui ring_buffer . Jika kita melihat outputnya kita melihat ada beberapa pernyataan yang dieksekusi untuk setiap DBCC CHECKCONSTRAINTS :

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


Output Acara yang Diperpanjang

Menggunakan Acara yang Diperpanjang untuk menggali cara kerja bagian dalam CHECKCONSTRAINTS adalah tugas yang menarik, tetapi yang benar-benar kami minati di sini adalah konsumsi sumber daya – khususnya I/O. Kami dapat menggabungkan physical_reads untuk setiap perintah cek untuk membandingkan I/O:

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


I/O Gabungan untuk Cek

Untuk memeriksa batasan, SQL Server harus membaca data untuk menemukan baris yang mungkin melanggar batasan. Definisi CK_SalesOrderDetailEnlarged_OrderQty batasannya adalah [OrderQty] > 0 . Batasan kunci asing, FK_SalesOrderDetailEnlarged_SalesOrderHeaderEnlarged_SalesOrderID , membuat hubungan pada SalesOrderID antara [Sales].[SalesOrderHeaderEnlarged] dan [Sales].[SalesOrderDetailEnlarged] tabel. Secara intuitif, sepertinya memeriksa batasan kunci asing akan membutuhkan lebih banyak I/O, karena SQL Server harus membaca data dari dua tabel. Namun, [SalesOrderID] ada di tingkat daun IX_SalesOrderHeaderEnlarged_SalesPersonID indeks nonclustered pada [Sales].[SalesOrderHeaderEnlarged] tabel, dan di IX_SalesOrderDetailEnlarged_ProductID indeks pada [Sales].[SalesOrderDetailEnlarged] meja. Dengan demikian, SQL Server memindai kedua indeks tersebut untuk membandingkan [SalesOrderID] nilai antara dua tabel. Ini membutuhkan lebih dari 19.000 pembacaan. Dalam kasus CK_SalesOrderDetailEnlarged_OrderQty kendala, [OrderQty] kolom tidak termasuk dalam indeks apa pun, sehingga pemindaian penuh dari indeks berkerumun terjadi, yang membutuhkan lebih dari 72.000 pembacaan.

Ketika semua kendala untuk tabel diperiksa, persyaratan I/O lebih tinggi daripada jika satu kendala diperiksa, dan mereka meningkat lagi ketika seluruh database diperiksa. Pada contoh di atas, [Sales].[SalesOrderHeaderEnlarged] dan [Sales].[SalesOrderDetailEnlarged] tabel secara tidak proporsional lebih besar dari tabel lain dalam database. Ini tidak biasa dalam skenario dunia nyata; sangat sering database memiliki beberapa tabel besar yang terdiri dari sebagian besar database. Saat menjalankan CHECKCONSTRAINTS untuk tabel ini, perhatikan potensi konsumsi sumber daya yang diperlukan untuk pemeriksaan. Jalankan pemeriksaan selama jam nonaktif jika memungkinkan untuk meminimalkan dampak pengguna. Jika pemeriksaan harus dijalankan selama jam kerja normal, memahami kendala apa yang ada, dan indeks apa yang ada untuk mendukung validasi, dapat membantu mengukur efek pemeriksaan. Anda dapat melakukan pemeriksaan di lingkungan pengujian atau pengembangan terlebih dahulu untuk memahami dampak kinerja, namun variasi mungkin ada berdasarkan perangkat keras, data yang sebanding, dll. Dan terakhir, ingatlah bahwa setiap kali Anda menjalankan perintah pemeriksaan yang menyertakan REPAIR_ALLOW_DATA_LOSS pilihan, ikuti perbaikan dengan DBCC CHECKCONSTRAINTS . Perbaikan basis data tidak memperhitungkan kendala apa pun karena kerusakan telah diperbaiki, jadi selain berpotensi kehilangan data, Anda mungkin berakhir dengan data yang melanggar satu atau beberapa kendala dalam basis data Anda.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Mitigasi Risiko Data melalui Penyembunyian Data

  2. Driver ODBC Google BigQuery

  3. Melacak CLR_MANUAL_EVENT yang tinggi menunggu

  4. Masalah Konfigurasi Log Transaksi

  5. Bisakah komentar menghambat kinerja prosedur tersimpan?