索引如何在幕后工作

时间:2016-03-19 15:21:05

标签: sql-server query-optimization non-clustered-index

我是个傻瓜。我知道索引对于性能提升是必要的,但我想知道它们在幕后的实际工作方式。事先,我曾经认为我们应该在where子句中包含的那些列上做索引(我意识到这是错误的)

例如,SELECT * from MARKS where marks_obtained > 50

考虑到这个表的主键上有一个聚簇索引,我在 marks_obtained 列中创建了一个非聚集索引,就像在where子句中那样。

我的感知:所以叶子节点将包含指向聚集索引的指针,而聚集索引指向实际行,它将选择整行(由于我的查询中的星号)

方案
我遇到了以下查询(来自AdventureWorks数据库,其中创建了非聚集索引)工作正常并且花费少于一秒来执行 3200000行直到新列被插入其中:

查询

SELECT x.* 
INTO#X
FROM dbo.bigProduct AS p
CROSS APPLY
(
SELECT TOP 1000 *
FROM dbo.bigTransactionHistory AS bth
WHERE 
     bth.ProductId = p.bth.ProductId 
ORDER BY
     TransactionDate DESC
) AS x
WHERE 
    p.ProductId BETWEEN 1000 AND 7500
GO

新插入的专栏

ALTER TABLE dbo.bigTransactionHistory 
ADD CustomerId INT NULL

插入上面的列后, 17秒!意味着慢17倍。非clusered索引现在缺少索引中的CustomerId列。在包括CustomerId之后,问题就消失了。

问题在将其添加到索引之前,CustomerId似乎是罪魁祸首。 但是如何???

1 个答案:

答案 0 :(得分:0)

执行计划会回答这个问题,但我会猜测:在添加附加列之后,非聚集索引不再足以满足查询。这可能导致索引不再使用。它还可以导致每行搜索一个聚簇索引。

学习阅读执行计划。为您测试的每个查询定期打开“实际执行计划”功能。