Почему в этом заявлении указано индексное сканирование в плане 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 ответ

Есть две причины...

  1. Потому что SQL Server не алгебраически манипулирует вашим предложением WHERE.
  2. Потому что есть 10 значений, которые соответствуют вашему второму запросу

Под первым комментарием я понимаю, что оптимизатор может видеть, что вы что-то делаете с intItemId, но он не пытается найти короткий путь. Вместо этого он должен выполнить /10 в каждом ряду, чтобы увидеть, каков результат.

(Он не знает, что 6000/10 = 600, а 5999 - нет. Поэтому он пробует это в каждом ряду.)

Это связано со второй причиной. Ваш вопрос подразумевает, что вы ожидаете только строки intItemId = 6000 быть возвращенным вашим вторым запросом. Но 6001/10 Через 6009/10 все равны 600 тоже из-за целочисленной арифметики. Итак, алгебраические манипуляции x/10=y становление x=y*10 не действует, когда вы делаете целочисленную арифметику. Что является одной из причин, почему оптимизатор не пытается.


Короче говоря: всякий раз, когда вы манипулируете индексированным полем практически любым способом, вы запрещаете использование индекса и получаете сканирование, а не поиск.

Другие вопросы по тегам