Поскольку и a, Table Scan
и a по Clustered Index Scan
существу сканируют все записи в таблице, почему сканирование кластерного индекса предположительно лучше?
Как пример - какая разница в производительности между следующими, когда есть много записей ?:
declare @temp table(
SomeColumn varchar(50)
)
insert into @temp
select 'SomeVal'
select * from @temp
-----------------------------
declare @temp table(
RowID int not null identity(1,1) primary key,
SomeColumn varchar(50)
)
insert into @temp
select 'SomeVal'
select * from @temp
В таблице без кластеризованного индекса (таблица кучи) страницы данных не связаны друг с другом - поэтому для обхода страниц требуется поиск в карте распределения индекса .
Однако в кластеризованной таблице страницы данных связаны двусвязным списком, что ускоряет последовательное сканирование. Конечно, в обмене, у вас есть накладные дела с сохранением страниц данных, чтобы на INSERT
, UPDATE
и DELETE
. Однако для таблицы кучи требуется вторая запись в IAM.
Если в вашем запросе есть RANGE
оператор (например:) SELECT * FROM TABLE WHERE Id BETWEEN 1 AND 100
, то кластеризованная таблица (находящаяся в гарантированном порядке) будет более эффективной - поскольку она может использовать страницы индекса для поиска релевантных страниц данных. Куча должна будет сканировать все строки, поскольку она не может полагаться на порядок.
И, конечно же, кластеризованный индекс позволяет вам выполнить CLUSTERED INDEX SEEK, который в значительной степени оптимален для производительности ... куча без индексов всегда приведет к сканированию таблицы.
Так:
Для вашего примера запроса, в котором вы выбираете все строки, единственное отличие состоит в двусвязном списке, который поддерживает кластерный индекс. Это должно сделать вашу кластерную таблицу чуть-чуть быстрее, чем куча с большим количеством строк.
Для запроса с
WHERE
предложением, которое может (хотя бы частично) быть удовлетворено кластеризованным индексом, вы выйдете вперед из-за упорядочения - поэтому вам не придется сканировать всю таблицу.Для запроса, который не удовлетворяется кластерным индексом, вы в значительной степени даже ... опять же, единственное отличие состоит в том, что это двусвязный список для последовательного сканирования. В любом случае, вы неоптимальный.
Ибо
INSERT
,UPDATE
иDELETE
куча может или не может победить. Куча не должна поддерживать порядок, но требует второй записи в IAM. Я думаю, что относительная разница в производительности будет незначительной, но также зависит от данных.
У Microsoft есть технический документ, который сравнивает кластерный индекс с эквивалентным некластеризованным индексом в куче (не совсем то, что я обсуждал выше, но близко). Их вывод заключается в том, чтобы кластеризовать индекс для всех таблиц. Я приложу все усилия, чтобы суммировать их результаты (опять же, обратите внимание, что они действительно сравнивают некластеризованный индекс с кластеризованным индексом - но я думаю, что он относительно сопоставим):
INSERT
производительность: кластерный индекс выигрывает примерно на 3% благодаря второй записи, необходимой для кучи.UPDATE
производительность: кластерный индекс выигрывает примерно на 8% благодаря второму поиску, необходимому для кучи.DELETE
производительность: кластерный индекс выигрывает примерно на 18% благодаря необходимому второму поиску и второму удалению из IAM для кучи.- единичная
SELECT
производительность: кластерный индекс выигрывает примерно на 16% благодаря второму поиску, необходимому для кучи. SELECT
Производительность диапазона : кластерный индекс выигрывает примерно на 29% из-за случайного упорядочения кучи.- одновременно
INSERT
: таблица кучи выигрывает на 30% под нагрузкой из-за разбиения страниц для кластеризованного индекса.
Сканирование таблицы должно проверять каждую строку таблицы. Сканирование кластеризованного индекса требует только сканирования индекса. Он не сканирует каждую запись в таблице. В этом-то и дело смысл индексов.
http://msdn.microsoft.com/en-us/library/aa216840(SQL.80).aspx
Логический и физический оператор сканирования кластерного индекса сканирует кластеризованный индекс, указанный в столбце Аргумент. При наличии необязательного предиката WHERE :() возвращаются только те строки, которые удовлетворяют предикату. Если столбец Argument содержит предложение ORDERED, обработчик запросов запросил, чтобы выходные данные строк были возвращены в порядке, в котором их отсортировал кластерный индекс. Если предложение ORDERED отсутствует, механизм хранения будет сканировать индекс оптимальным способом (не гарантируя сортировку вывода).
http://msdn.microsoft.com/en-us/library/aa178416(SQL.80).aspx
Логический и физический оператор Table Scan извлекает все строки из таблицы, указанной в столбце Argument. Если в столбце Аргумент появляется предикат WHERE :(), возвращаются только те строки, которые удовлетворяют предикату.