Database
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Database

Xem xét DBCC CHECKCONSTRAINTS và I / O

Một yếu tố phổ biến được sử dụng trong thiết kế cơ sở dữ liệu là ràng buộc. Các ràng buộc có nhiều loại khác nhau (ví dụ:mặc định, duy nhất) và thực thi tính toàn vẹn của (các) cột mà chúng tồn tại. Khi được triển khai tốt, các ràng buộc là một thành phần mạnh mẽ trong thiết kế cơ sở dữ liệu vì chúng ngăn không cho dữ liệu không đáp ứng các tiêu chí đã đặt vào cơ sở dữ liệu. Tuy nhiên, các ràng buộc có thể bị vi phạm bằng cách sử dụng các lệnh như WITH NOCHECKIGNORE_CONSTRAINTS . Ngoài ra, khi sử dụng REPAIR_ALLOW_DATA_LOSS với bất kỳ DBCC CHECK nào lệnh sửa lỗi cơ sở dữ liệu bị hỏng, các ràng buộc không được xem xét.

Do đó, có thể có dữ liệu không hợp lệ trong cơ sở dữ liệu - dữ liệu không tuân theo ràng buộc hoặc dữ liệu không còn duy trì mối quan hệ khóa chính-khóa ngoài dự kiến. SQL Server bao gồm DBCC CHECKCONSTRAINTS câu lệnh để tìm dữ liệu vi phạm các ràng buộc. Sau khi thực thi bất kỳ tùy chọn sửa chữa nào, hãy chạy DBCC CHECKCONSTRAINTS cho toàn bộ cơ sở dữ liệu để đảm bảo không có sự cố nào và có thể có lúc thích hợp để chạy CHECKCONSTRAINTS cho một ràng buộc chọn hoặc một bảng. Duy trì tính toàn vẹn của dữ liệu là rất quan trọng và mặc dù việc chạy DBCC CHECKCONSTRAINTS không phải là điều điển hình theo lịch trình để tìm dữ liệu không hợp lệ, khi bạn cần chạy nó, bạn nên hiểu tác động về hiệu suất mà nó có thể tạo ra.

DBCC CHECKCONSTRAINTS có thể thực thi cho một ràng buộc, một bảng hoặc toàn bộ cơ sở dữ liệu. Giống như các lệnh kiểm tra khác, có thể mất nhiều thời gian để hoàn thành và sẽ tiêu tốn tài nguyên hệ thống, đặc biệt là đối với cơ sở dữ liệu lớn hơn. Không giống như các lệnh kiểm tra khác, CHECKCONSTRAINTS không sử dụng ảnh chụp nhanh cơ sở dữ liệu.

Với Sự kiện mở rộng, chúng tôi có thể kiểm tra việc sử dụng tài nguyên khi thực thi DBCC CHECKCONSTRAINTS cho bảng. Để thể hiện rõ hơn tác động, tôi đã chạy tập lệnh Create Enlarged AdventureWorks Tables.sql từ Jonathan Kehayias (blog | @SQLPoolBoy) để tạo các bảng lớn hơn. Tập lệnh của Jonathan chỉ tạo chỉ mục cho các bảng, do đó, các câu lệnh bên dưới là cần thiết để thêm một số ràng buộc đã chọn:

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

Chúng tôi có thể xác minh những ràng buộc nào tồn tại bằng cách sử dụng sp_helpconstraint :

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


sp_helpconstraint output

Khi các ràng buộc tồn tại, chúng ta có thể so sánh việc sử dụng tài nguyên cho DBCC CHECKCONSTRAINTS cho một ràng buộc duy nhất, một bảng và toàn bộ cơ sở dữ liệu sử dụng Sự kiện mở rộng. Trước tiên, chúng tôi sẽ tạo một phiên chỉ ghi lại sp_statement_completed sự kiện, bao gồm sql_text hành động và gửi kết quả đến 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

Tiếp theo, chúng ta sẽ bắt đầu phiên và chạy từng DBCC CHECKCONSTRAINT các lệnh, sau đó xuất bộ đệm vòng sang một bảng tạm thời để thao tác. Lưu ý rằng DBCC DROPCLEANBUFFERS thực hiện trước mỗi lần kiểm tra để mỗi lần kiểm tra bắt đầu từ bộ đệm lạnh, giữ trường kiểm tra mức độ.

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

Phân tích cú pháp ring_buffer vào bảng tạm thời có thể mất thêm thời gian (khoảng 20 giây trên máy của tôi), nhưng việc truy vấn dữ liệu lặp lại từ bảng tạm thời nhanh hơn so với thông qua ring_buffer . Nếu chúng ta nhìn vào kết quả đầu ra, chúng ta thấy có một số câu lệnh được thực thi cho mỗi DBCC CHECKCONSTRAINTS :

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


Đầu ra sự kiện mở rộng

Sử dụng Sự kiện mở rộng để tìm hiểu hoạt động bên trong của CHECKCONSTRAINTS là một nhiệm vụ thú vị, nhưng điều chúng tôi thực sự quan tâm ở đây là mức tiêu thụ tài nguyên - cụ thể là I / O. Chúng tôi có thể tổng hợp physical_reads cho mỗi lệnh kiểm tra để so sánh I / O:

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


I / O tổng hợp cho séc

Để kiểm tra một ràng buộc, SQL Server phải đọc qua dữ liệu để tìm bất kỳ hàng nào có thể vi phạm ràng buộc. Định nghĩa của CK_SalesOrderDetailEnlarged_OrderQty ràng buộc là [OrderQty] > 0 . Ràng buộc khóa ngoại, FK_SalesOrderDetailEnlarged_SalesOrderHeaderEnlarged_SalesOrderID , thiết lập mối quan hệ trên SalesOrderID giữa [Sales].[SalesOrderHeaderEnlarged][Sales].[SalesOrderDetailEnlarged] những cái bàn. Trực quan có vẻ như việc kiểm tra ràng buộc khóa ngoại sẽ yêu cầu nhiều I / O hơn, vì SQL Server phải đọc dữ liệu từ hai bảng. Tuy nhiên, [SalesOrderID] tồn tại trong cấp độ lá của IX_SalesOrderHeaderEnlarged_SalesPersonID chỉ mục không hợp nhất trên [Sales].[SalesOrderHeaderEnlarged] và trong IX_SalesOrderDetailEnlarged_ProductID lập chỉ mục trên [Sales].[SalesOrderDetailEnlarged] bàn. Như vậy, SQL Server quét hai chỉ mục đó để so sánh [SalesOrderID] giá trị giữa hai bảng. Điều này chỉ cần hơn 19.000 lần đọc. Trong trường hợp của CK_SalesOrderDetailEnlarged_OrderQty ràng buộc, [OrderQty] cột không được bao gồm trong bất kỳ chỉ mục nào, vì vậy quá trình quét toàn bộ chỉ mục được phân nhóm sẽ xảy ra, yêu cầu hơn 72.000 lần đọc.

Khi tất cả các ràng buộc cho một bảng được kiểm tra, các yêu cầu I / O sẽ cao hơn so với nếu một ràng buộc duy nhất được kiểm tra và chúng sẽ tăng trở lại khi toàn bộ cơ sở dữ liệu được kiểm tra. Trong ví dụ trên, [Sales].[SalesOrderHeaderEnlarged][Sales].[SalesOrderDetailEnlarged] các bảng lớn hơn không cân xứng so với các bảng khác trong cơ sở dữ liệu. Điều này không phải là hiếm trong các tình huống trong thế giới thực; cơ sở dữ liệu rất thường xuyên có một số bảng lớn bao gồm một phần lớn cơ sở dữ liệu. Khi chạy CHECKCONSTRAINTS đối với các bảng này, hãy lưu ý về mức tiêu thụ tài nguyên tiềm năng cần thiết cho việc kiểm tra. Kiểm tra trong giờ ngoài giờ khi có thể để giảm thiểu tác động của người dùng. Trong trường hợp séc phải chạy trong giờ làm việc bình thường, việc hiểu những ràng buộc nào tồn tại và những chỉ mục nào tồn tại để hỗ trợ xác thực, có thể giúp đánh giá tác dụng của séc. Trước tiên, bạn có thể thực hiện kiểm tra trong môi trường thử nghiệm hoặc phát triển để hiểu tác động của hiệu suất, nhưng các biến thể sau đó có thể tồn tại dựa trên phần cứng, dữ liệu có thể so sánh, v.v. Và cuối cùng, hãy nhớ rằng bất kỳ lúc nào bạn chạy lệnh kiểm tra bao gồm REPAIR_ALLOW_DATA_LOSS tùy chọn, hãy làm theo cách sửa chữa với DBCC CHECKCONSTRAINTS . Việc sửa chữa cơ sở dữ liệu không tính đến bất kỳ ràng buộc nào vì đã sửa lỗi hỏng, vì vậy ngoài khả năng mất dữ liệu, bạn có thể nhận được dữ liệu vi phạm một hoặc nhiều ràng buộc trong cơ sở dữ liệu của mình.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Thiết kế cơ sở dữ liệu để ghi nhật ký kiểm tra

  2. Thêm cột vào bảng trong SQL

  3. Kết nối PolyBase với Salesforce.com

  4. Các triệu chứng trên người quan sát và loại chờ đợi

  5. Khóa ứng viên trong thiết kế cơ sở dữ liệu là gì?