Ponieważ inne odpowiedzi już wskazują, że SQL Server może, ale nie musi, jawnie zapewnić, że wiersze są sortowane w indeksie klastrowym przed insert
.
DMLRequestSort
Zależy to od tego, czy operator indeksu klastrowanego w planie ma ustawioną właściwość (która z kolei zależy od szacunkowej liczby wstawianych wierszy).
Jeśli okaże się, że SQL Server nie docenia tego z jakiegokolwiek powodu, możesz skorzystać z dodania wyrażenia jawnego ORDER BY
do SELECT
zapytania, aby zminimalizować podziały stron i wynikającą z tego fragmentację INSERT
operacji
Przykład:
use tempdb;
GO
CREATE TABLE T(N INT PRIMARY KEY,Filler char(2000))
CREATE TABLE T2(N INT PRIMARY KEY,Filler char(2000))
GO
DECLARE @T TABLE (U UNIQUEIDENTIFIER PRIMARY KEY DEFAULT NEWID(),N int)
INSERT INTO @T(N)
SELECT number
FROM master..spt_values
WHERE type = 'P' AND number BETWEEN 0 AND 499
/*Estimated row count wrong as inserting from table variable*/
INSERT INTO T(N)
SELECT T1.N*1000 + T2.N
FROM @T T1, @T T2
/*Same operation using explicit sort*/
INSERT INTO T2(N)
SELECT T1.N*1000 + T2.N
FROM @T T1, @T T2
ORDER BY T1.N*1000 + T2.N
SELECT avg_fragmentation_in_percent,
fragment_count,
page_count,
avg_page_space_used_in_percent,
record_count
FROM sys.dm_db_index_physical_stats(2, OBJECT_ID('T'), NULL, NULL, 'DETAILED')
;
SELECT avg_fragmentation_in_percent,
fragment_count,
page_count,
avg_page_space_used_in_percent,
record_count
FROM sys.dm_db_index_physical_stats(2, OBJECT_ID('T2'), NULL, NULL, 'DETAILED')
;
Programy, które T
są bardzo rozdrobnione
avg_fragmentation_in_percent fragment_count page_count avg_page_space_used_in_percent record_count
---------------------------- -------------------- -------------------- ------------------------------ --------------------
99.3116118225536 92535 92535 67.1668272794663 250000
99.5 200 200 74.2868173956017 92535
0 1 1 32.0978502594514 200
Ale T2
fragmentacja jest minimalna
avg_fragmentation_in_percent fragment_count page_count avg_page_space_used_in_percent record_count
---------------------------- -------------------- -------------------- ------------------------------ --------------------
0.376 262 62500 99.456387447492 250000
2.1551724137931 232 232 43.2438349394613 62500
0 1 1 37.2374598468001 232
I odwrotnie, czasem możesz zmusić SQL Server do niedoceniania liczby wierszy, gdy wiesz, że dane są już wstępnie posortowane i chcesz uniknąć niepotrzebnego sortowania. Jednym z godnych uwagi przykładów jest wstawianie dużej liczby wierszy do tabeli za pomocą newsequentialid
klastrowego klucza indeksu. W wersjach SQL Server wcześniejszych niż Denali SQL Server dodaje niepotrzebną i potencjalnie kosztowną operację sortowania . Można tego uniknąć
DECLARE @var INT =2147483647
INSERT INTO Foo
SELECT TOP (@var) *
FROM Bar
SQL Server oszacuje następnie, że zostanie wstawionych 100 wierszy, niezależnie od rozmiaru, Bar
który jest poniżej progu, do którego sortowanie jest dodawane do planu. Jednak, jak wskazano w komentarzach poniżej, oznacza to, że wkładka niestety nie będzie mogła skorzystać z minimalnego logowania.