Оптимизация индекса SQL Server 2008 - кластерный поиск по сравнению с некластеризованным включением

Это длинный и сложный вопрос теории оптимизации индекса. Это не домашнее задание, хотя я впервые столкнулся с этим вопросом на пробном экзамене для Microsoft 70-432. Первоначальный вопрос касался общей оптимизации запросов, но затем я обнаружил это странное поведение, которое не смог объяснить.

Сначала таблица:

CREATE TABLE Invoice_details (
Invoice_id int NOT NULL,
Customer_id int NOT NULL,
Invoice_date datetime DEFAULT GETDATE() NULL,
Amount_total int NULL,
Serial_num int IDENTITY (1,1) NOT NULL)

Теперь кластеризованный индекс и два индекса для тестирования:

CREATE UNIQUE CLUSTERED INDEX [ix_serial] ON [dbo].[Invoice_details] ([Serial_num] ASC)
/* Below is the "original" index */
CREATE NONCLUSTERED INDEX [ix_invoice_customer] ON [dbo].[Invoice_details] 
    ([Invoice_id] ASC,[Customer_id] ASC)
/* Below is the "optimized" index (adds one included field) */
CREATE NONCLUSTERED INDEX [ix_invoice_customer_inc] ON [dbo].[Invoice_details] 
    ([Invoice_id] ASC,[Customer_id] ASC) INCLUDE ([Invoice_date])

Я также добавил в таблицу несколько случайных тестовых данных - 100000 строк. Invoice_id, Customer_id и Amount_total получили свои собственные случайные значения (диапазон 1000-9999), а Invoice_date получил GETDATE () плюс случайное количество секунд (диапазон 1000-9999). Я могу предоставить реальный распорядок, который я использовал, но не думал, что подробности будут уместны.

И наконец, запрос:

SELECT Invoice_id,Customer_id,Invoice_date FROM Invoice_details WHERE Customer_id=1234;

Очевидно, что первым шагом запроса будет сканирование некластеризованного индекса. Независимо от того, какой индекс используется, этот первый шаг вернет такое же количество строк индекса. С «исходным» индексом следующим шагом будет поиск по кластеризованному индексу для получения Invoice_date, за которым следует внутреннее СОЕДИНЕНИЕ между двумя наборами. При «оптимизированном» индексе это поле включается в лист индекса, поэтому планировщик сразу же возвращает результаты.

Какой индекс приводит к более быстрому выполнению и почему?


person Wanna-be-guru    schedule 06.09.2011    source источник
comment
BTW: Вы собираетесь рассказать нам о полученных вами результатах, которые вас удивили?   -  person Martin Smith    schedule 06.09.2011
comment
Я не ожидал, что включенный индекс будет работать хуже. В исходном тестовом вопросе моим ответом было создание нового некластеризованного индекса для Customer_id. Это было неправильно ... тест показал, что включенное поле было скорее оптимизацией. Во время моих тестов результаты показали, что не только мой метод был быстрее, но и включенное поле фактически снизило производительность по сравнению с сканированием кластерного индекса, которое оно использовало по умолчанию.   -  person Wanna-be-guru    schedule 10.09.2011


Ответы (2)


Это зависит ... от переломного момента.

person Bogdan Sahlean    schedule 06.09.2011

Если предположить, что нет таких проблем, как фрагментация, тогда все сводится к избирательности запроса.

2 индекса очень похожи. Поскольку «оптимизированный» включает дополнительный столбец на конечных страницах, полное сканирование этого индекса может означать, что необходимо прочитать больше страниц по сравнению с исходным. Однако, если должно быть возвращено более нескольких строк, я бы ожидал, что выгода от отсутствия необходимости в поиске очень быстро перевесит этот незначительный недостаток.

person Martin Smith    schedule 06.09.2011
comment
@@ sahlean - Я просто пытался проголосовать за ваш ответ, потому что вы меня опередили, включив в него ссылка на переломный момент, но вы удалили ее! - person Martin Smith; 06.09.2011
comment
Я думал, что ответ (мой ответ) слишком прост. - person Bogdan Sahlean; 06.09.2011
comment
@@ sahlean - Нет, я думаю, эта ссылка действительно все говорит. Я сам собирался сделать ссылку на него и был очень раздражен тем, что вы меня опередили! - person Martin Smith; 06.09.2011
comment
Ваш ответ (вы оба) верен, как показали дальнейшие эксперименты. Дополнительное поле include увеличивает размер индекса, тем самым замедляя сканирование из-за увеличения количества чтений страниц. После определенной точки (т. Е. Размера таблицы) преимущество в скорости переходит к кластеризованному поиску. Указывает на sahlean первым. :) Большое спасибо. - person Wanna-be-guru; 10.09.2011