Какая разница между сканированием таблиц и сканированием индексов кластеров?

Поскольку как a Table Scan, так и 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

Ответ 1

В таблице без кластеризованного индекса (таблица кучи) страницы данных не связаны друг с другом, поэтому для перемещения страниц требуется поиск в карте распределения индексов.

Однако в кластеризованной таблице есть страницы данных, связанные в двусвязном списке - ускорение последовательного сканирования. Конечно, взамен, у вас есть накладные расходы на поддержание страниц данных в порядке на 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 для кучи.
  • single SELECT производительность: кластеризованный индекс выигрывает примерно на 16% из-за второго поиска, необходимого для кучи.
  • диапазон SELECT производительность: кластеризованный индекс выигрывает примерно на 29% из-за случайного упорядочения для кучи.
  • concurrent INSERT: таблица кучи выигрывает на 30% под нагрузкой из-за разбиения страниц для кластерного индекса.

Ответ 2

http://msdn.microsoft.com/en-us/library/aa216840(SQL.80).aspx

Оператор логического и физического сканирования кластерного индекса сканирует кластеризованный индекс, указанный в столбце "Аргумент" . Когда присутствует дополнительный предикат WHERE:(), возвращаются только те строки, которые удовлетворяют предикату. Если столбец "Аргумент" содержит предложение ORDERED, процессор запросов запросил, чтобы вывод строк возвращался в том порядке, в котором кластеризованный индекс отсортировал их. Если предложение ORDERED отсутствует, механизм хранения сканирует индекс оптимальным образом (не гарантируя сортировку вывода).

http://msdn.microsoft.com/en-us/library/aa178416(SQL.80).aspx

Логический и физический оператор сканирования таблицы извлекает все строки из таблицы, указанной в столбце "Аргумент" . Если в столбце Аргумент появляется предикат WHERE:(), возвращаются только те строки, которые удовлетворяют предикату.

Ответ 3

Сканирование таблицы должно проверять каждую строку таблицы. Для сканирования кластерного индекса требуется только сканирование индекса. Он не проверяет каждую запись в таблице. Это, по сути, индексы.