1

我有两条语句返回相同的结果,但产生不同的执行计划。

  • 第一 >>> 索引搜索
  • 第二个>>>索引扫描

谁能解释为什么?

例子

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
4

1 回答 1

2

有两个原因...

  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这是优化器不尝试的部分原因。


简而言之:每当您以几乎任何方式操作索引字段时,您都会阻止使用索引并获得扫描而不是查找。

于 2013-05-30T01:55:02.053 回答