2010-03-03 4 views
3

У меня есть следующий запрос:SQL Index Question: Почему SQL Server предпочитает этот индекс NONCLUSTERED для CLUSTERED?

SELECT 
    COUNT(*) 
FROM 
    FirstTable ft 
     INNER JOIN SecondTable st ON ft.STID = st.STID 

Как вы можете догадаться, «STID» является первичным ключом на «SecondTable» ... и «FirstTable» будет иметь указатель на эту вторую таблицу. Вот показатели, которые у меня есть:

FirstTable: NONCLUSTERED INDEX на колонке "STID"

SecondTable: CLUSTERED PRIMARY KEY INDEX на "STID"

Приведенный выше запрос дает мне стоимость поддерева 19.90 и принимает 2 секунды.

После запуска советника по настройке базы данных для этого запроса они предложили сделать очень похожим индексом, который у меня был на второй таблице ... но некластеризован. Итак, я попробовал это с этими результатами.

FirstTable: NONCLUSTERED INDEX на колонке "STID"

SecondTable: NONCLUSTERED INDEX на "STID"

Теперь, выше запрос дает мне стоимость поддерева 10,97 и принимает < 1 второй!

Этот 100% разрушает мой мозг ... Почему индекс NONCLUSTERED работает быстрее, чем индекс CLUSTERED в этом сценарии?

ответ

7

Поскольку ваш запрос не извлекает никаких реальных записей из таблиц, он просто подсчитывается.

С некластеризованными индексами он просто объединяет два индекса (размер которых меньше по размеру, чем таблицы), используя, скорее всего, MERGE JOIN.

С кластеризованным индексом он должен присоединиться к таблице и некластеризованному индексу. Таблица больше, и для ее прохождения требуется больше времени.

Если вы выдаете запрос следующим образом:

SELECT SUM(first_table_field + second_table_field) 
FROM FirstTable ft 
INNER JOIN 
     SecondTable st 
ON  ft.STID = st.STID 

, который извлекает фактические значения, вы увидите преимущество кластеризации.

+0

Это было быстро! - Это именно тот ясный, логичный ответ, который я искал. - Конечно, это не мой * реальный * запрос, но он действительно помогает моему реальному запросу (который не использовал столбцы из этой таблицы, а просто использовал его для внутреннего соединения/фильтра) - Thx! –

+0

@Quassnoi: извините, этот ответ для меня не имеет смысла. Вы сказали: «с кластеризованным индексом он должен присоединиться к таблице». Кластеризованный индекс - это индекс. Исходный запрос на самом деле не извлекает какой-либо столбец, поэтому все, что ему нужно, должно соответствовать значениям ключа, то есть нужно сканировать только страницы индекса. Если вы посмотрите на эти фотографии, https://technet.microsoft.com/en-us/library/ms177443%28v=sql.105%29.aspx и https://technet.microsoft.com/en-us/library /ms177484%28v=sql.105%29.aspx, разница в том, что в кластерном индексе у вас есть данные в листовых узлах, но запрос не нужно идти на уровень листа. – costa

+0

@quassnoi: продолжить ... если не использовать * что-то делает для оптимизатора запросов, и лучше использовать count (1). Основываясь на моем опыте работы с SQL Server, особенно 2008 и 2008 R2, заключается в том, что иногда он делает эти мозговые мертвые вещи, которых вы никогда не ожидали. – costa