Почему в этом заявлении указано индексное сканирование в плане Exec?
У меня есть два утверждения, которые возвращают один и тот же результат, но дают разные планы выполнения.
- Первая >>> Поиск по индексу
- Второе >>> индексное сканирование
Кто-нибудь может объяснить почему?
пример
CREATE TABLE OrderDetails (intOrderId int, intItemId int, dtOrderDate Datetime, intQty int, intPrice int, intDiscount int)
GO
CREATE CLUSTERED INDEX CI_OrderId ON OrderDetails(intOrderId)
GO
CREATE NONCLUSTERED INDEX NCI_ItemId ON OrderDetails(intItemId)
GO
-- Populate Data
SET NOCOUNT ON
DECLARE @i int
SET @i =10
WHILE @i < 100000
BEGIN
INSERT INTO OrderDetails
VALUES (@i, round(rand()*9999,0)+1, getdate() - round(rand()*999,0), round(rand()*99,0)+1, round(rand()*9999,0)+1, round(rand()*99,0)+1)
SET @i = @i + 1
END
GO
-- Check Execution Plans
-- NCI SEEK
SELECT intOrderId, intItemId
FROM OrderDetails
WHERE intItemId = 600 * 10
-- NCI SCAN
SELECT intOrderId, intItemId
FROM OrderDetails
WHERE intItemId/10 = 600
1 ответ
Есть две причины...
- Потому что SQL Server не алгебраически манипулирует вашим предложением WHERE.
- Потому что есть 10 значений, которые соответствуют вашему второму запросу
Под первым комментарием я понимаю, что оптимизатор может видеть, что вы что-то делаете с intItemId
, но он не пытается найти короткий путь. Вместо этого он должен выполнить /10
в каждом ряду, чтобы увидеть, каков результат.
(Он не знает, что 6000/10 = 600, а 5999 - нет. Поэтому он пробует это в каждом ряду.)
Это связано со второй причиной. Ваш вопрос подразумевает, что вы ожидаете только строки intItemId = 6000
быть возвращенным вашим вторым запросом. Но 6001/10
Через 6009/10
все равны 600
тоже из-за целочисленной арифметики. Итак, алгебраические манипуляции x/10=y
становление x=y*10
не действует, когда вы делаете целочисленную арифметику. Что является одной из причин, почему оптимизатор не пытается.
Короче говоря: всякий раз, когда вы манипулируете индексированным полем практически любым способом, вы запрещаете использование индекса и получаете сканирование, а не поиск.