Bài đăng này cung cấp thông tin mới về các điều kiện tiên quyết đối với tải số lượng lớn được ghi nhật ký tối thiểu khi sử dụng INSERT...SELECT
vào bảng được lập chỉ mục .
Cơ sở nội bộ cho phép các trường hợp này được gọi là FastLoadContext
. Nó có thể được kích hoạt từ SQL Server 2008 đến 2014 bao gồm cả cờ theo dõi được ghi lại 610. Từ SQL Server 2016 trở đi, FastLoadContext
được bật theo mặc định; cờ theo dõi là không bắt buộc.
Không có FastLoadContext
, chỉ mục chèn có thể được ghi nhật ký tối thiểu những cái đó thành một trống rỗng chỉ mục nhóm không có chỉ mục phụ, như được đề cập trong phần hai của loạt bài này. ghi nhật ký tối thiểu các điều kiện cho bảng heap không lập chỉ mục đã được đề cập trong phần một.
Để biết thêm thông tin cơ bản, hãy xem Hướng dẫn tải hiệu suất dữ liệu và Đội hổ ghi chú về các thay đổi hành vi đối với SQL Server 2016.
Bối cảnh tải nhanh
Xin nhắc lại nhanh, RowsetBulk
cơ sở (được đề cập trong phần 1 và 2) cho phép ghi nhật ký tối thiểu tải số lượng lớn cho:
- heap rỗng và không trống bảng với:
- Khóa bảng; và
- Không có chỉ mục phụ.
- Các bảng được nhóm trống , với:
- Khóa bảng; và
- Không có chỉ mục phụ; và
-
DMLRequestSort=true
trên Chèn chỉ mục theo cụm toán tử.
FastLoadContext
đường dẫn mã bổ sung hỗ trợ cho ghi nhật ký tối thiểu và đồng thời tải hàng loạt trên:
- Rỗng và không rỗng được nhóm chỉ mục b-cây.
- Rỗng và không rỗng không bao gồm chỉ mục b-cây được duy trì bởi một chuyên dụng Chèn chỉ mục nhà điều hành kế hoạch.
FastLoadContext
cũng yêu cầu DMLRequestSort=true
trên nhà điều hành gói tương ứng trong mọi trường hợp.
Bạn có thể nhận thấy sự trùng lặp giữa RowsetBulk
và FastLoadContext
cho các bảng được phân nhóm trống không có chỉ mục phụ. A TABLOCK
gợi ý là không bắt buộc với FastLoadContext
nhưng không bắt buộc phải vắng mặt hoặc. Do đó, một chèn phù hợp với TABLOCK
vẫn có thể đủ điều kiện cho ghi nhật ký tối thiểu qua FastLoadContext
nếu nó không thành công RowsetBulk
chi tiết kiểm tra.
FastLoadContext
có thể bị vô hiệu hóa trên SQL Server 2016 bằng cách sử dụng cờ theo dõi được tài liệu hóa 692. Sự kiện mở rộng kênh gỡ lỗi fastloadcontext_enabled
có thể được sử dụng để theo dõi FastLoadContext
sử dụng trên mỗi phân vùng chỉ mục (tập hợp hàng). Sự kiện này không kích hoạt cho RowsetBulk
tải.
Ghi nhật ký hỗn hợp
Một INSERT...SELECT
duy nhất câu lệnh sử dụng FastLoadContext
có thể ghi nhật ký đầy đủ một số hàng trong khi ghi nhật ký tối thiểu những người khác.
Các hàng được chèn từng hàng một bởi Chèn chỉ mục nhà điều hành và đã ghi đầy đủ trong các trường hợp sau:
- Tất cả các hàng được thêm vào đầu tiên trang chỉ mục, nếu chỉ mục trống khi bắt đầu hoạt động.
- Các hàng đã được thêm vào hiện có các trang chỉ mục.
- Hàng đã di chuyển giữa các trang bằng cách tách trang.
Nếu không, các hàng từ luồng chèn theo thứ tự sẽ được thêm vào trang hoàn toàn mới sử dụng tối ưu hóa và ghi nhật ký tối thiểu đường dẫn mã. Khi càng nhiều hàng càng tốt được ghi vào trang mới, nó sẽ được liên kết trực tiếp vào cấu trúc chỉ mục mục tiêu hiện có.
Trang mới được thêm vào sẽ không nhất thiết phải đầy (mặc dù rõ ràng đó là trường hợp lý tưởng) vì SQL Server phải cẩn thận để không thêm hàng vào trang mới thuộc về một cách hợp lý trên một hiện có trang mục lục. Trang mới sẽ được 'ghép vào' chỉ mục dưới dạng một đơn vị, vì vậy chúng tôi không thể có bất kỳ hàng nào trên trang mới thuộc về nơi khác. Đây chủ yếu là một vấn đề khi thêm hàng trong phạm vi khóa chỉ mục hiện có, thay vì trước khi bắt đầu hoặc sau khi kết thúc phạm vi khóa chỉ mục hiện có.
Nó vẫn có thể để thêm các trang mới trong phạm vi khóa chỉ mục hiện tại, nhưng các hàng mới phải sắp xếp cao hơn khóa cao nhất trên trước trang chỉ mục hiện có và sắp xếp thấp hơn khóa thấp nhất trên sau trang chỉ mục hiện có. Để có cơ hội tốt nhất đạt được ghi nhật ký tối thiểu trong những trường hợp này, hãy đảm bảo các hàng được chèn không trùng lặp với các hàng hiện có càng nhiều càng tốt.
Điều kiện DMLRequestSort
Hãy nhớ rằng FastLoadContext
chỉ có thể được kích hoạt nếu DMLRequestSort
được đặt thành true cho Chèn chỉ mục tương ứng trong kế hoạch thực thi.
Có hai đường dẫn mã chính có thể đặt DMLRequestSort
thành đúng để chèn chỉ mục. Một trong hai con đường trả về true là đủ.
1. FOptimizeInsert
sqllang!CUpdUtil::FOptimizeInsert
mã yêu cầu:
- Hơn 250 hàng ước tính được chèn vào; và
- Nhiều hơn 2 trang ước tính chèn kích thước dữ liệu; và
- Chỉ mục mục tiêu phải có ít hơn 3 trang lá .
Các điều kiện này giống với RowsetBulk
trên một chỉ mục được phân nhóm trống, với yêu cầu bổ sung cho không quá hai trang cấp lá chỉ mục. Lưu ý cẩn thận rằng điều này đề cập đến kích thước của chỉ mục hiện có trước khi chèn, không kích thước ước tính của dữ liệu sẽ được thêm vào.
Tập lệnh dưới đây là bản sửa đổi của bản trình diễn được sử dụng trong các phần trước của loạt bài này. Nó hiển thị ghi nhật ký tối thiểu khi ít hơn ba trang chỉ mục được điền trước kiểm tra INSERT...SELECT
chạy. Lược đồ bảng kiểm tra sao cho 130 hàng có thể vừa trên một trang 8KB khi tắt phiên bản hàng cho cơ sở dữ liệu. Hệ số trong TOP
đầu tiên mệnh đề có thể được thay đổi để xác định số lượng trang chỉ mục hiện có trước đó kiểm tra INSERT...SELECT
được thực thi:
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 -- 130 rows per page for this table -- structure with row versioning off INSERT dbo.Test (c1) SELECT TOP (3 * 130) -- Change the 3 here CHECKSUM(NEWID()) FROM master.dbo.spt_values AS SV; GO -- Show physical index statistics -- to confirm the number of pages SELECT DDIPS.index_type_desc, DDIPS.alloc_unit_type_desc, DDIPS.page_count, DDIPS.record_count, DDIPS.avg_record_size_in_bytes FROM sys.dm_db_index_physical_stats ( DB_ID(), OBJECT_ID(N'dbo.Test', N'U'), 1, -- Index ID NULL, -- Partition ID 'DETAILED' ) AS DDIPS WHERE DDIPS.index_level = 0; -- leaf level only GO -- Clear the plan cache DBCC FREEPROCCACHE; GO -- Clear the log CHECKPOINT; GO -- Main test INSERT dbo.Test (c1) SELECT TOP (269) 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)'; GO
Khi chỉ mục được nhóm được tải trước với 3 trang , phụ trang thử nghiệm được ghi nhật ký đầy đủ (lược bỏ các bản ghi chi tiết nhật ký giao dịch cho ngắn gọn):
Khi bảng được tải trước chỉ 1 hoặc 2 trang , phụ trang thử nghiệm được ghi nhật ký tối thiểu :
Khi bảng không được tải trước với bất kỳ trang nào, kiểm tra tương đương với việc chạy bản trình diễn bảng nhóm trống từ phần hai, nhưng không có TABLOCK
gợi ý:
130 hàng đầu tiên được ghi nhật ký đầy đủ . Điều này là do chỉ mục trống trước khi chúng tôi bắt đầu và 130 hàng vừa với trang đầu tiên. Hãy nhớ rằng trang đầu tiên luôn được ghi lại đầy đủ khi FastLoadContext
được sử dụng và chỉ mục trống trước đó. 139 hàng còn lại được chèn với ghi nhật ký tối thiểu .
Nếu một TABLOCK
gợi ý được thêm vào phần chèn, tất cả các trang được ghi nhật ký tối thiểu (bao gồm cả lần đầu tiên) vì tải chỉ mục được phân cụm trống hiện đủ điều kiện cho RowsetBulk
cơ chế (với chi phí lấy Sch-M
khóa).
2. FDemandRowsSortedForPerformance
Nếu FOptimizeInsert
kiểm tra không thành công, DMLRequestSort
vẫn có thể được đặt thành true bởi tập hợp các bài kiểm tra thứ hai trong sqllang!CUpdUtil::FDemandRowsSortedForPerformance
mã số. Các điều kiện này phức tạp hơn một chút, vì vậy sẽ hữu ích khi xác định một số tham số:
-
P
- số trang cấp lá hiện có trong chỉ mục mục tiêu . -
I
- ước tính số hàng cần chèn. -
R
=P
/I
(các trang mục tiêu trên mỗi hàng được chèn). -
T
- số lượng phân vùng đích (1 phân vùng chưa được phân vùng).
Logic để xác định giá trị của DMLRequestSort
sau đó là:
- Nếu
P <= 16
trả về false , nếu không thì :- Nếu
R < 8
:- Nếu
P > 524
trả về true , nếu không thì false .
- Nếu
- Nếu
R >= 8
:- Nếu
T > 1
vàI > 250
trả về true , nếu không thì false .
- Nếu
- Nếu
Các bài kiểm tra trên được đánh giá bởi bộ xử lý truy vấn trong quá trình biên dịch kế hoạch. Có một điều kiện cuối cùng được đánh giá bằng mã công cụ lưu trữ (IndexDataSetSession::WakeUpInternal
) tại thời điểm thực hiện:
-
DMLRequestSort
hiện tại là true ; và -
I >= 100
.
Tiếp theo, chúng tôi sẽ chia nhỏ tất cả logic này thành các phần có thể quản lý được.
Hơn 16 trang mục tiêu hiện có
Bài kiểm tra đầu tiên P <= 16
có nghĩa là các chỉ mục có ít hơn 17 trang lá hiện có sẽ không đủ điều kiện cho FastLoadContext
thông qua đường dẫn mã này. Để hoàn toàn rõ ràng về điểm này, P
là số trang cấp độ lá trong chỉ mục mục tiêu trước đó INSERT...SELECT
được thực thi.
Để chứng minh phần logic này, chúng tôi sẽ tải trước bảng nhóm thử nghiệm có 16 trang Dữ liệu. Điều này có hai tác dụng quan trọng (hãy nhớ cả hai đường dẫn mã phải trả về false kết thúc bằng false giá trị cho DMLRequestSort
):
- Nó đảm bảo rằng
FOptimizeInsert
trước đó kiểm tra không thành công , bởi vì điều kiện thứ ba không được đáp ứng (P < 3
). -
P <= 16
điều kiện trongFDemandRowsSortedForPerformance
cũng sẽ không được đáp ứng.
Do đó, chúng tôi mong đợi FastLoadContext
không được kích hoạt. Tập lệnh demo đã sửa đổi là:
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 -- 130 rows per page for this table -- structure with row versioning off INSERT dbo.Test (c1) SELECT TOP (16 * 130) -- 16 pages CHECKSUM(NEWID()) FROM master.dbo.spt_values AS SV; GO -- Show physical index statistics -- to confirm the number of pages SELECT DDIPS.index_type_desc, DDIPS.alloc_unit_type_desc, DDIPS.page_count, DDIPS.record_count, DDIPS.avg_record_size_in_bytes FROM sys.dm_db_index_physical_stats ( DB_ID(), OBJECT_ID(N'dbo.Test', N'U'), 1, -- Index ID NULL, -- Partition ID 'DETAILED' ) AS DDIPS WHERE DDIPS.index_level = 0; -- leaf level only GO -- Clear the plan cache DBCC FREEPROCCACHE; GO -- Clear the log CHECKPOINT; GO -- Main test INSERT dbo.Test (c1) SELECT TOP (269) CHECKSUM(NEWID()) FROM master.dbo.spt_values AS SV1 CROSS JOIN master.dbo.spt_values AS SV2; 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)';
Tất cả 269 hàng đều được ghi nhật ký đầy đủ như dự đoán:
Lưu ý rằng bất kể chúng tôi đặt số lượng hàng mới để chèn cao bao nhiêu, tập lệnh ở trên sẽ không bao giờ sản xuất ghi nhật ký tối thiểu vì P <= 16
kiểm tra (và P < 3
kiểm tra trong FOptimizeInsert
).
Nếu bạn chọn tự chạy bản demo với số lượng hàng lớn hơn, hãy bình luận phần hiển thị các bản ghi nhật ký giao dịch riêng lẻ, nếu không, bạn sẽ phải đợi rất lâu và SSMS có thể bị lỗi. (Công bằng mà nói, dù sao nó cũng có thể làm được điều đó, nhưng tại sao lại thêm rủi ro.)
Tỷ lệ số trang trên mỗi hàng được chèn
Nếu có 17 trở lên trang lá trong chỉ mục hiện có, P <= 16
trước đó thử nghiệm sẽ không thất bại. Phần logic tiếp theo đề cập đến tỷ lệ trang hiện có đến hàng mới được chèn . Điều này cũng phải vượt qua để đạt được ghi nhật ký tối thiểu . Xin nhắc lại, các điều kiện liên quan là:
- Tỷ lệ
R
=P
/I
. - Nếu
R < 8
:- Nếu
P > 524
trả về true , nếu không thì false .
- Nếu
Chúng ta cũng phải nhớ kiểm tra công cụ lưu trữ cuối cùng cho ít nhất 100 hàng:
-
I >= 100
.
Tổ chức lại các điều kiện đó một chút, tất cả những điều sau đây phải đúng:
-
P > 524
(các trang chỉ mục hiện có) -
I >= 100
(các hàng được chèn ước tính) -
P / I < 8
(tỷ lệR
)
Có nhiều cách để đáp ứng ba điều kiện đó đồng thời. Hãy chọn các giá trị tối thiểu có thể có cho P
(525) và I
(100) đưa ra một R
giá trị của (525/100) =5,25. Điều này đáp ứng (R < 8
thử nghiệm), vì vậy chúng tôi hy vọng sự kết hợp này sẽ dẫn đến ghi nhật ký tối thiểu :
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 -- 130 rows per page for this table -- structure with row versioning off INSERT dbo.Test (c1) SELECT TOP (525 * 130) -- 525 pages CHECKSUM(NEWID()) FROM master.dbo.spt_values AS SV1 CROSS JOIN master.dbo.spt_values AS SV2; GO -- Show physical index statistics -- to confirm the number of pages SELECT DDIPS.index_type_desc, DDIPS.alloc_unit_type_desc, DDIPS.page_count, DDIPS.record_count, DDIPS.avg_record_size_in_bytes FROM sys.dm_db_index_physical_stats ( DB_ID(), OBJECT_ID(N'dbo.Test', N'U'), 1, -- Index ID NULL, -- Partition ID 'DETAILED' ) AS DDIPS WHERE DDIPS.index_level = 0; -- leaf level only GO -- Clear the plan cache DBCC FREEPROCCACHE; GO -- Clear the log CHECKPOINT; GO -- Main test INSERT dbo.Test (c1) SELECT TOP (100) CHECKSUM(NEWID()) FROM master.dbo.spt_values AS SV1 CROSS JOIN master.dbo.spt_values AS SV2; 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)';
100 hàng INSERT...SELECT
thực sự là ghi nhật ký tối thiểu :
Giảm ước tính đã chèn các hàng vào 99 (ngắt I >= 100
), và / hoặc giảm số lượng trang chỉ mục hiện có xuống còn 524 (ngắt P > 524
) dẫn đến ghi nhật ký đầy đủ . Chúng tôi cũng có thể thực hiện các thay đổi sao cho R
không còn ít hơn 8 để tạo ra ghi nhật ký đầy đủ . Ví dụ:đặt P = 1000
và I = 125
đưa ra R = 8
, với các kết quả sau:
125 hàng được chèn đã được ghi nhật ký đầy đủ như mong đợi. (Điều này không phải do ghi nhật ký đầy đủ trang đầu tiên, vì trước đó chỉ mục không có sản phẩm nào.)
Tỷ lệ trang cho các chỉ mục được phân vùng
Nếu tất cả các thử nghiệm trước đó không thành công, một thử nghiệm còn lại yêu cầu R >= 8
và chỉ có thể hài lòng khi số lượng phân vùng (T
) lớn hơn 1 và có hơn 250 ước tính các hàng được chèn (I
). Nhớ lại:
- Nếu
R >= 8
:- Nếu
T > 1
vàI > 250
trả về true , nếu không thì false .
- Nếu
Một sự tinh tế:Đối với phân vùng chỉ mục, quy tắc cho biết tất cả các hàng của trang đầu tiên được ghi lại đầy đủ (đối với chỉ mục trống ban đầu) áp dụng cho mỗi phân vùng . Đối với một đối tượng có 15.000 phân vùng, điều đó có nghĩa là 15.000 trang 'đầu tiên' được ghi đầy đủ.
Tóm tắt và Kết luận
Các công thức và thứ tự đánh giá được mô tả trong phần thân dựa trên việc kiểm tra mã bằng trình gỡ lỗi. Chúng được trình bày dưới dạng biểu thị chặt chẽ thời gian và thứ tự được sử dụng trong mã thực.
Có thể sắp xếp lại và đơn giản hóa các điều kiện đó một chút, để tạo ra một bản tóm tắt ngắn gọn hơn về các yêu cầu thực tế đối với ghi nhật ký tối thiểu khi chèn vào b-tree bằng cách sử dụng INSERT...SELECT
. Các biểu thức được tinh chỉnh bên dưới sử dụng ba tham số sau:
-
P
=số lượng hiện có lập chỉ mục các trang cấp độ lá. -
I
= ước tính số hàng cần chèn. -
S
= ước tính chèn kích thước dữ liệu vào các trang 8KB.
Đặt hàng loạt tải
- Sử dụng
sqlmin!RowsetBulk
. - Yêu cầu trống mục tiêu chỉ mục được phân nhóm với
TABLOCK
(hoặc tương đương). - Yêu cầu
DMLRequestSort=true
trên Chèn chỉ mục theo cụm toán tử. -
DMLRequestSort
được đặttrue
ifI > 250
vàS > 2
. - Tất cả các hàng được chèn đều được ghi nhật ký tối thiểu .
- Một
Sch-M
khóa ngăn chặn truy cập bảng đồng thời.
Ngữ cảnh tải nhanh
- Sử dụng
sqlmin!FastLoadContext
. - Bật tính năng ghi nhật ký tối thiểu chèn vào các chỉ mục b-tree:
- Theo nhóm hoặc không phân nhóm.
- Có hoặc không có khóa bàn.
- Chỉ mục mục tiêu trống hoặc không.
- Yêu cầu
DMLRequestSort=true
trên Chèn chỉ mục được liên kết nhà điều hành kế hoạch. - Chỉ các hàng được viết cho trang mới được tải hàng loạt và ghi nhật ký tối thiểu .
- Trang đầu tiên của một chỉ mục trống trước đây phân vùng luôn được đăng nhập đầy đủ .
- Tối thiểu tuyệt đối là
I >= 100
. - Yêu cầu cờ theo dõi 610 trước SQL Server 2016.
- Có sẵn theo mặc định từ SQL Server 2016 (cờ theo dõi 692 vô hiệu hóa).
DMLRequestSort
được đặt true
cho:
- Bất kỳ chỉ mục nào (được phân vùng hoặc không) nếu:
-
I > 250
vàP < 3
vàS > 2
; hoặc -
I >= 100
vàP > 524
vàP < I * 8
-
Đối với chỉ các chỉ mục được phân vùng (với> 1 phân vùng), DMLRequestSort
cũng được đặt true
nếu:
-
I > 250
vàP > 16
vàP >= I * 8
Có một vài trường hợp thú vị phát sinh từ FastLoadContext
đó điều kiện:
- Tất cả chèn vào không phân vùng chỉ mục có từ 3 đến 524 (bao gồm) các trang lá hiện có sẽ được ghi lại đầy đủ bất kể số lượng và tổng kích thước của các hàng được thêm vào. Điều này sẽ ảnh hưởng rõ rệt nhất đến các phần chèn lớn đối với các bảng nhỏ (nhưng không trống).
- Tất cả chèn vào phân vùng chỉ mục có từ 3 đến 16 các trang hiện có sẽ được ghi nhật ký đầy đủ .
- Chèn lớn thành lớn không phân vùng chỉ mục có thể không được ghi nhật ký tối thiểu do sự bất bình đẳng
P < I * 8
. KhiP
lớn, một ước tính tương ứng lớn số hàng được chèn (I
) bắt buộc. Ví dụ:một chỉ mục có 8 triệu trang không thể hỗ trợ ghi nhật ký tối thiểu khi chèn 1 triệu hàng trở xuống.
Nonclustered indexes
Các cân nhắc và tính toán tương tự được áp dụng cho các chỉ mục được nhóm trong bản trình diễn áp dụng cho nonclustered chỉ mục b-cây cũng vậy, miễn là chỉ mục được duy trì bởi nhà điều hành gói chuyên dụng (a rộng hoặc mỗi chỉ mục kế hoạch). Chỉ mục không phân tán được duy trì bởi toán tử bảng cơ sở (ví dụ: Chèn chỉ mục theo cụm ) không đủ điều kiện cho FastLoadContext
.
Lưu ý rằng các tham số công thức cần phải được đánh giá mới cho mỗi nonclustered toán tử chỉ mục - kích thước hàng được tính toán, số lượng trang chỉ mục hiện có và ước tính số lượng.
Nhận xét chung
Chú ý đến ước tính số lượng thấp tại Chèn chỉ mục toán tử, vì chúng sẽ ảnh hưởng đến I
và S
thông số. Nếu không đạt đến ngưỡng do lỗi ước tính bản số, phần chèn sẽ được ghi nhật ký đầy đủ .
Hãy nhớ rằng DMLRequestSort
được lưu trữ trong bộ nhớ cache với kế hoạch - nó không được đánh giá trên mỗi lần thực hiện một kế hoạch được sử dụng lại. Điều này có thể giới thiệu một dạng của Vấn đề nhạy cảm tham số nổi tiếng (còn được gọi là “đánh giá tham số”).
Giá trị của P
(các trang lá chỉ mục) không được làm mới ở đầu mỗi câu lệnh. Triển khai hiện tại lưu trữ giá trị cho toàn bộ lô . Điều này có thể có tác dụng phụ không mong muốn. Ví dụ:TRUNCATE TABLE
trong cùng một đợt dưới dạng INSERT...SELECT
sẽ không đặt lại P
về 0 đối với các phép tính được mô tả trong bài viết này - chúng sẽ tiếp tục sử dụng giá trị cắt bớt trước và biên dịch lại sẽ không hữu ích. Một cách giải quyết là gửi các thay đổi lớn theo từng đợt riêng biệt.
Cờ theo dõi
Có thể buộc FDemandRowsSortedForPerformance
để trả về 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. Khi TF 2332 hoạt động, số lượng hàng ước tính để chèn vẫn cần phải là ít nhất 100 . TF 2332 ảnh hưởng đến ghi nhật ký tối thiểu quyết định cho FastLoadContext
chỉ (nó có hiệu quả đối với các đống được phân vùng xa như DMLRequestSort
có liên quan, nhưng không ảnh hưởng đến chính heap, vì FastLoadContext
chỉ áp dụng cho các chỉ mục).
A rộng / mỗi chỉ mục Hình dạng kế hoạch để duy trì chỉ mục không phân tán có thể được buộc cho các bảng lưu trữ hàng sử dụng cờ theo dõi 8790 (không được ghi lại chính thức, nhưng được đề cập trong bài viết Cơ sở kiến thức cũng như trong bài viết của tôi như được liên kết cho TF2332 ở trên).
Đọc liên quan
Tất cả do Sunil Agarwal từ nhóm SQL Server:
- Tối ưu hoá Nhập hàng loạt là gì?
- Tối ưu hoá Nhập hàng loạt (Ghi nhật ký Tối thiểu)
- Thay đổi ghi nhật ký tối thiểu trong SQL Server 2008
- Thay đổi ghi nhật ký tối thiểu trong SQL Server 2008 (phần 2)
- Thay đổi ghi nhật ký tối thiểu trong SQL Server 2008 (phần 3)