Это длинный и сложный вопрос теории оптимизации индекса. Это не домашнее задание, хотя я впервые столкнулся с этим вопросом на пробном экзамене для 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, за которым следует внутреннее СОЕДИНЕНИЕ между двумя наборами. При «оптимизированном» индексе это поле включается в лист индекса, поэтому планировщик сразу же возвращает результаты.
Какой индекс приводит к более быстрому выполнению и почему?