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

Ghi nhật ký tối thiểu với CHÈN… CHỌN vào các bảng được phân nhóm trống

Giới thiệu

Đạt được ghi nhật ký tối thiểu sử dụng INSERT...SELECT vào một trống rỗng mục tiêu chỉ mục theo cụm không hoàn toàn đơn giản như được mô tả trong Hướng dẫn tải hiệu suất dữ liệu .

Bài đăng này cung cấp chi tiết mới về các yêu cầu đối với ghi nhật ký tối thiểu khi mục tiêu chèn là một chỉ mục được phân cụm truyền thống trống. (Từ “truyền thống” ở đó loại trừ columnstore tối ưu hóa bộ nhớ (‘Hekaton’) các bảng nhóm). Để biết các điều kiện áp dụng khi bảng đích là một đống, hãy xem bài viết trước trong loạt bài này.

Summary cho Clustered Tables

Hướng dẫn hiệu suất tải dữ liệu chứa bản tóm tắt cấp cao về các điều kiện cần thiết để ghi nhật ký tối thiểu thành các bảng được nhóm lại:

Bài đăng này chỉ liên quan đến hàng trên cùng . Nó nói rằng TABLOCKORDER gợi ý là bắt buộc, với ghi chú cho biết:

Nếu bạn đang sử dụng phương thức INSERT… SELECT, gợi ý ORDER không cần phải được chỉ định, nhưng các hàng phải theo cùng thứ tự với chỉ mục được phân nhóm.

Nếu sử dụng CHÈN SỐ LƯỢNG LỚN, bạn phải sử dụng gợi ý đơn hàng.

Mục tiêu trống có Khóa bảng

Hàng trên cùng tóm tắt gợi ý rằng tất cả các lần chèn vào chỉ mục được nhóm trống sẽ được ghi nhật ký tối thiểu miễn là TABLOCKORDER gợi ý được chỉ định. TABLOCK gợi ý là bắt buộc để kích hoạt RowSetBulk cơ sở như được sử dụng cho đống tải trọng lớn của bảng. ORDER gợi ý là bắt buộc để đảm bảo các hàng đến Chèn chỉ mục theo cụm toán tử kế hoạch trong chỉ mục mục tiêu thứ tự chính . Nếu không có đảm bảo này, SQL Server có thể thêm các hàng chỉ mục không được sắp xếp chính xác, điều này sẽ không tốt.

Không giống như các phương pháp tải hàng loạt khác, điều này không thể để chỉ định ORDER bắt buộc gợi ý về INSERT...SELECT tuyên bố. Gợi ý này không giống nhau như sử dụng ORDER BY trên INSERT...SELECT tuyên bố. ORDER BY mệnh đề trên INSERT chỉ đảm bảo cách bất kỳ danh tính các giá trị được chỉ định, không phải thứ tự chèn hàng.

Đối với INSERT...SELECT , SQL Server đưa ra quyết định của riêng mình liệu có đảm bảo các hàng được hiển thị trong Chèn chỉ mục theo cụm toán tử theo thứ tự chính hoặc không. Kết quả của đánh giá này được hiển thị trong các kế hoạch thực thi thông qua DMLRequestSort thuộc tính của Chèn nhà điều hành. DMLRequestSort tài sản phải được đặt thành true cho INSERT...SELECT vào một chỉ mục để được ghi nhật ký tối thiểu . Khi nó được đặt thành false , ghi nhật ký tối thiểu không thể xảy ra.

DMLRequestSort đặt thành true đảm bảo duy nhất có thể chấp nhận được thứ tự đầu vào chèn cho SQL Server. Người ta có thể kiểm tra kế hoạch thực hiện và dự đoán rằng các hàng phải / sẽ / phải đến theo thứ tự chỉ mục nhóm, nhưng không có đảm bảo nội bộ cụ thể được cung cấp bởi DMLRequestSort , đánh giá đó không có giá trị gì.

Khi DMLRequestSort sự thật , SQL Server có thể giới thiệu một Sắp xếp rõ ràng toán tử trong kế hoạch thực hiện. Nếu nội bộ nó có thể đảm bảo việc đặt hàng theo những cách khác, thì Sắp xếp có thể được bỏ qua. Nếu cả hai lựa chọn thay thế sắp xếp và không sắp xếp đều có sẵn, trình tối ưu hóa sẽ tạo dựa trên chi phí sự lựa chọn. Phân tích chi phí không tính đến ghi nhật ký tối thiểu trực tiếp; nó được thúc đẩy bởi những lợi ích mong đợi của I / O tuần tự và tránh tách trang.

Điều kiện DMLRequestSort

Cả hai bài kiểm tra sau phải vượt qua để SQL Server chọn đặt DMLRequestSort thành đúng khi chèn vào một chỉ mục được nhóm trống với khóa bảng được chỉ định:

  • Ước tính có hơn 250 hàng ở phía đầu vào của Chèn chỉ mục theo cụm nhà điều hành;
  • Một ước tính kích thước dữ liệu của hơn 2 trang . Kích thước dữ liệu ước tính không phải là số nguyên, vì vậy, kết quả của 2,001 trang sẽ đáp ứng điều kiện này.

(Điều này có thể nhắc nhở bạn về các điều kiện cho đống ghi nhật ký tối thiểu , nhưng ước tính bắt buộc kích thước dữ liệu ở đây là hai trang thay vì tám trang.)

Tính toán Kích thước Dữ liệu

Kích thước dữ liệu ước tính phép tính ở đây tuân theo cùng các câu hỏi được mô tả trong bài viết trước cho đống, ngoại trừ RID 8 byte không có mặt.

Đối với SQL Server 2012 trở về trước, điều này có nghĩa là 5 byte bổ sung mỗi hàng được bao gồm trong phép tính kích thước dữ liệu:Một byte cho một bit nội bộ cờ và bốn byte cho uniquifier (được sử dụng trong tính toán ngay cả đối với các chỉ mục duy nhất, không lưu trữ bộ thống nhất ).

Đối với SQL Server 2014 trở lên, uniquifier được bỏ qua một cách chính xác cho duy nhất chỉ mục, nhưng một byte bổ sung cho bit nội bộ cờ được giữ lại.

Demo

Tập lệnh sau sẽ được chạy trên phiên bản SQL Server phát triển trong cơ sở dữ liệu thử nghiệm mới đặt để sử dụng SIMPLE hoặc BULK_LOGGED mô hình phục hồi.

Bản trình diễn tải 268 hàng vào một bảng phân cụm hoàn toàn mới bằng cách sử dụng INSERT...SELECT với TABLOCK và báo cáo về các bản ghi nhật ký giao dịch được tạo.

IF OBJECT_ID(N'dbo.Test', N'U') IS NOT NULL
BEGIN
    DROP TABLE dbo.Test;
END;
GO
CREATE TABLE dbo.Test 
(
    id integer NOT NULL IDENTITY
        CONSTRAINT [PK dbo.Test (id)]
        PRIMARY KEY,
    c1 integer NOT NULL,
    padding char(45) NOT NULL
        DEFAULT ''
);
GO
-- Clear the log
CHECKPOINT;
GO
-- Insert rows
INSERT dbo.Test WITH (TABLOCK) 
    (c1)
SELECT TOP (268)
    CHECKSUM(NEWID())
FROM master.dbo.spt_values AS SV;
GO
-- Show log entries
SELECT
    FD.Operation,
    FD.Context,
    FD.[Log Record Length],
    FD.[Log Reserve],
    FD.AllocUnitName,
    FD.[Transaction Name],
    FD.[Lock Information],
    FD.[Description]
FROM sys.fn_dblog(NULL, NULL) AS FD;
GO
-- Count the number of  fully-logged rows
SELECT 
    [Fully Logged Rows] = COUNT_BIG(*) 
FROM sys.fn_dblog(NULL, NULL) AS FD
WHERE 
    FD.Operation = N'LOP_INSERT_ROWS'
    AND FD.Context = N'LCX_CLUSTERED'
    AND FD.AllocUnitName = N'dbo.Test.PK dbo.Test (id)';

(Nếu bạn chạy tập lệnh trên SQL Server 2012 trở xuống, hãy thay đổi TOP trong script từ 268 đến 252, vì lý do sẽ được giải thích trong giây lát.)

Kết quả cho thấy rằng tất cả các hàng được chèn đã được ghi nhật ký đầy đủ mặc dù trống bảng nhóm mục tiêu và TABLOCK gợi ý:

Kích thước dữ liệu chèn được tính toán

Các thuộc tính kế hoạch thực thi của Chèn chỉ mục theo cụm cho thấy rằng DMLRequestSort được đặt thành false . Điều này là do mặc dù số hàng ước tính cần chèn là hơn 250 (đáp ứng yêu cầu đầu tiên), nhưng tính toán kích thước dữ liệu không vượt quá hai trang 8KB.

Chi tiết tính toán (dành cho SQL Server 2014 trở đi) như sau:

  • Tổng số độ dài cố định kích thước cột = 54 byte :
    • Nhập id 104 bit =1 byte (nội bộ).
    • Nhập id 56 integer =4 byte (id cột).
    • Nhập id 56 integer =4 byte (c1 cột).
    • Nhập id 175 char(45) =45 byte (padding cột).
  • Bản đồ bit rỗng = 3 byte .
  • Tiêu đề hàng overhead = 4 byte .
  • Kích thước hàng được tính toán =54 + 3 + 4 = 61 byte .
  • Kích thước dữ liệu được tính toán =61 byte * 268 hàng = 16.348 byte .
  • Các trang dữ liệu được tính toán =16.384 / 8192 = 1.99560546875 .

Kích thước hàng được tính toán (61 byte) khác với kích thước lưu trữ hàng thực (60 byte) bởi một byte siêu dữ liệu nội bộ có trong luồng chèn. Tính toán cũng không tính đến 96 byte được sử dụng trên mỗi trang bởi tiêu đề trang hoặc những thứ khác như chi phí lập phiên bản hàng. Tính toán tương tự trên SQL Server 2012 thêm 4 byte nữa trên mỗi hàng cho bộ thu thập thông tin (không có trong các chỉ mục duy nhất như đã đề cập trước đây). Các byte thừa có nghĩa là sẽ có ít hàng phù hợp hơn trên mỗi trang:

  • Kích thước hàng được tính toán =61 + 4 = 65 byte .
  • Kích thước dữ liệu được tính toán =65 byte * 252 hàng = 16.380 byte
  • Các trang dữ liệu được tính toán =16.380 / 8192 = 1.99951171875 .

Thay đổi TOP mệnh đề từ 268 hàng đến 269 (hoặc từ 252 đến 253 cho năm 2012) thực hiện phép tính kích thước dữ liệu dự kiến ​​ chỉ vượt qua ngưỡng tối thiểu 2 trang:

  • SQL Server 2014
    • 61 byte * 269 hàng =16.409 byte.
    • 16.409/8192 = 2.0030517578125 trang.
  • SQL Server 2012
    • 65 byte * 253 hàng =16,445 byte.
    • 16.445 / 8192 = 2.0074462890625 trang.

Với điều kiện thứ hai bây giờ cũng được thỏa mãn, DMLRequestSort được đặt thành true ghi nhật ký tối thiểu đạt được, như được hiển thị trong kết quả bên dưới:

Một số điểm lưu ý khác:

  • Tổng số 79 bản ghi nhật ký được tạo, so với 328 bản ghi cho phiên bản được ghi nhật ký đầy đủ. Ít bản ghi nhật ký hơn là kết quả mong đợi của việc ghi nhật ký tối thiểu.
  • LOP_BEGIN_XACT bản ghi trong ghi nhật ký tối thiểu các bản ghi dự trữ một lượng tương đối lớn không gian nhật ký (mỗi bản ghi 9436 byte).
  • Một trong những tên giao dịch được liệt kê trong bản ghi nhật ký là “xây dựng chỉ mục ngoại tuyến” . Mặc dù chúng tôi không yêu cầu tạo một chỉ mục như vậy, nhưng việc tải hàng loạt các hàng vào một chỉ mục trống về cơ bản là cùng một thao tác.
  • được ghi nhật ký đầy đủ insert có khóa độc quyền cấp bảng (Tab-X ), trong khi ghi nhật ký tối thiểu insert thực hiện sửa đổi giản đồ (Sch-M ) giống như cách xây dựng chỉ mục ngoại tuyến 'thực'.
  • Tải hàng loạt bảng được phân nhóm trống bằng cách sử dụng INSERT...SELECT với TABLOCKDMRequestSort đặt thành true sử dụng RowsetBulk , giống như cơ chế ghi nhật ký tối thiểu tải đống đã thực hiện trong bài viết trước.

Các ước tính về số lượng

Chú ý đến ước tính số lượng thấp tại Chèn chỉ mục theo cụm nhà điều hành. Nếu một trong các ngưỡng được yêu cầu để đặt DMLRequestSort thành đúng không đạt được do ước tính số lượng không chính xác, phần chèn sẽ được ghi nhật ký đầy đủ , bất kể số lượng hàng thực tế và tổng kích thước dữ liệu gặp phải tại thời điểm thực thi.

Ví dụ:thay đổi TOP mệnh đề trong tập lệnh demo để sử dụng một biến kết quả trong một số lượng cố định đoán 100 hàng, dưới mức tối thiểu 251 hàng:

-- Insert rows
DECLARE @NumRows bigint = 269;
 
INSERT dbo.Test WITH (TABLOCK) 
    (c1)
SELECT TOP (@NumRows)
    CHECKSUM(NEWID())
FROM master.dbo.spt_values AS SV;

Plan Cache

DMLRequestSort tài sản được lưu như một phần của kế hoạch đã lưu trong bộ nhớ cache. Khi một kế hoạch đã lưu trong bộ nhớ cache được sử dụng lại , giá trị của DMLRequestSort không được tính toán lại tại thời điểm thực thi, trừ khi xảy ra biên dịch lại. Lưu ý rằng việc biên dịch lại không xảy ra đối với TRIVIAL kế hoạch dựa trên những thay đổi trong thống kê hoặc số lượng bảng.

Một cách để tránh bất kỳ hành vi không mong muốn nào do bộ nhớ đệm là sử dụng OPTION (RECOMPILE) gợi ý. Điều này sẽ đảm bảo cài đặt thích hợp cho DMLRequestSort được tính toán lại, với chi phí biên dịch trên mỗi lần thực thi.

Cờ theo dõi

Có thể buộc DMLRequestSort được đặt thành true bằng cách đặt không có giấy tờ và không được hỗ trợ cờ theo dõi 2332, như tôi đã viết trong Tối ưu hóa truy vấn T-SQL thay đổi dữ liệu. Rất tiếc, điều này không ảnh hưởng đến ghi nhật ký tối thiểu đủ điều kiện cho các bảng được phân nhóm trống - phần chèn vẫn phải được ước tính là hơn 250 hàng và 2 trang. Cờ theo dõi này không ảnh hưởng đến ghi nhật ký tối thiểu khác các tình huống, được đề cập trong phần cuối cùng của loạt bài này.

Tóm tắt

Tải hàng loạt trống chỉ mục nhóm bằng cách sử dụng INSERT...SELECT sử dụng lại RowsetBulk cơ chế được sử dụng để tải hàng loạt bảng đống. Điều này yêu cầu khóa bảng (thường đạt được với TABLOCK gợi ý) và một ORDER gợi ý. Không có cách nào để thêm ORDER gợi ý cho một INSERT...SELECT tuyên bố. Do đó, đạt được ghi nhật ký tối thiểu vào một bảng được phân nhóm trống yêu cầu DMLRequestSort thuộc tính của Chèn chỉ mục theo cụm toán tử được đặt thành true . Điều này đảm bảo tới SQL Server mà các hàng được hiển thị cho Chèn toán tử sẽ đến theo thứ tự khóa chỉ mục đích. Hiệu ứng giống như khi sử dụng ORDER gợi ý có sẵn cho các phương pháp chèn hàng loạt khác như BULK INSERTbcp .

Để DMLRequestSort được đặt thành true , phải có:

  • Hơn 250 hàng ước tính được chèn vào;
  • Một ước tính chèn kích thước dữ liệu của hơn hai trang .

ước tính chèn tính toán kích thước dữ liệu không khớp với kết quả của việc nhân kế hoạch thực thi số hàng ước tính kích thước hàng ước tính thuộc tính ở đầu vào của Chèn nhà điều hành. Tính toán nội bộ (không chính xác) bao gồm một hoặc nhiều cột nội bộ trong luồng chèn, không tồn tại trong chỉ mục cuối cùng. Tính toán nội bộ cũng không tính đến tiêu đề trang hoặc các chi phí khác như lập phiên bản hàng.

Khi kiểm tra hoặc gỡ lỗi ghi nhật ký tối thiểu vấn đề, hãy cẩn thận với ước tính số lượng thấp và nhớ rằng cài đặt của DMLRequestSort được lưu vào bộ nhớ đệm như một phần của kế hoạch thực thi.

Phần cuối cùng của loạt bài này trình bày chi tiết các điều kiện cần thiết để đạt được ghi nhật ký tối thiểu mà không sử dụng RowsetBulk cơ chế. Các cơ sở này tương ứng trực tiếp với các cơ sở mới được thêm dưới cờ theo dõi 610 vào SQL Server 2008, sau đó được thay đổi để được bật theo mặc định từ SQL Server 2016 trở đi.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Nhân bản cơ sở dữ liệu với PSDatabaseClone

  2. Thay đổi trên Bảng lớn trong RDS Giải pháp cho bảng đầy đủ Lỗi

  3. Làm thế nào để bỏ một cột trong SQL?

  4. Ứng dụng thời gian thực là gì?

  5. Viết lại các truy vấn để cải thiện hiệu suất