STATISTICS IO für den parallelen Index-Scan

7

Angenommen, es gibt eine Tabelle mit Clustered-Index

create table [a_table] ([key] binary(900) unique clustered);

und einige Daten

insert into [a_table] ([key])
select top (1000000) row_number() over (order by @@spid)
from sys.all_columns a cross join sys.all_columns b;

Durch Überprüfen der Speicherstatistik dieser Tabelle

select st.index_level, page_count = sum(st.page_count)
from sys.dm_db_index_physical_stats(
    db_id(), object_id('a_table'), NULL, NULL, 'DETAILED') st
group by rollup (st.index_level)
order by grouping_id(st.index_level), st.index_level desc;

man kann sehen

index_level page_count
----------- ----------
8           1
7           7
6           30
5           121
4           487
3           1952
2           7812
1           31249
0           125000
NULL        166659

Diese Tabelle umfasst insgesamt 166659 Seiten.

Jedoch Tabellenscan

set nocount on;
set statistics io, time on;
declare @cnt int;
select @cnt = count(1) from [a_table];
set statistics io, time off;

produziert

Table 'a_table'. Scan count 5, logical reads 484367, ...
CPU time = 1757 ms,  elapsed time = 460 ms.

Fast dreimal so viele logische Lesevorgänge wie in der Tabelle. Als ich den Abfrageplan untersuchte, stellte ich fest, dass SqlServer einen parallelen Index-Scan verwendete. Und hier stellt sich der erste Teil der Frage.

Wie wird ein paralleler Index-Scan durchgeführt, bei dem SqlServer so viele logische Lesevorgänge ausführt?

Festlegen option (maxdop 1), um Parallelität zu unterdrücken

set nocount on;
set statistics io, time on;
declare @cnt2 int;
select @cnt2 = count(1) from [a_table] option (maxdop 1);
set statistics io, time off;

resultierte zu

Table 'a_table'. Scan count 1, logical reads 156257, ...
CPU time = 363 ms,  elapsed time = 367 ms.

Der Vergleich von Statistiken für den parallelen und den nicht parallelen Index-Scan führt in diesem Fall zu dem Schluss, dass es manchmal besser ist, den parallelen Index-Scan zu vermeiden. Und hier stellt sich der zweite Teil der Frage.

Wann sollte ich mir Gedanken über den parallelen Index-Scan machen? Wann sollte es vermieden / unterdrückt werden? Was sind die Best Practices?


Die obigen Ergebnisse werden am erhalten

Microsoft SQL Server 2014 (SP2) (KB3171021) - 12.0.5000.0 (X64)

ich ein
quelle

Antworten:

6

Wenn Sie der Tabelle einen TABLOCKoder einen READUNCOMMITTEDHinweis hinzufügen , erhalten Sie einen nach Zuordnung geordneten Scan , der die gleiche Anzahl logischer Lesevorgänge wie die Anzahl der Seiten in der Tabelle meldet.

Bei einem Scan mit Zuordnungsreihenfolge verwendet SQL Server Zuordnungsstrukturen, um die Verteilung von Seiten zwischen Threads zu steuern. IAM-Seitenzugriffe werden nicht berücksichtigt STATISTICS IO.

Bei einem Scan ohne Zuordnung ordnet SQL Server den Scan mithilfe von Indexschlüsseln in Unterbereiche auf. Für jede interne Operation zum Suchen und Verteilen einer neuen Seite oder eines Seitenbereichs (basierend auf einem Schlüsselbereich) an einen Arbeitsthread muss auf die oberen Ebenen des B-Baums zugegriffen werden. Diese Zugriffe werden ebenso gezählt STATISTICS IOwie die Zugriffe der oberen Ebene, die von Arbeitsthreads ausgeführt werden, wenn der Startpunkt ihres aktuellen Bereichs ermittelt wird. Alle diese zusätzlichen Lesevorgänge der oberen Ebene berücksichtigen den Unterschied, den Sie sehen.

Meiner Meinung nach wird der E / A-Statistik zu viel Gewicht beigemessen. Passen Sie Ihre Abfragen an das an, was für Sie und Ihre Arbeitsbelastung wichtig ist. Dies ist oft die verstrichene Zeit, aber auch die Ressourcennutzung kann ein Faktor sein. Keine Metrik ist "am besten" - Sie sollten eine ausgewogene Sichtweise haben.

Paul White 9
quelle