0

我有一个表格MY_TABLE约900万行。查询性能悖论:独特的群集与非唯一的非群集索引

该表共有38列。这是有关我的问题的列有:

  • RECORD_ID:身份,BIGINT,具有独特的聚集索引
  • RECORD_CREATED:日期时间,与非唯一&非聚集索引现在

我运行以下两个查询,自然期望第一个执行速度更快,因为数据按具有唯一聚簇索引的列进行排序,但它以某种方式执行了271次(!)较慢。

SELECT TOP 1 
    RECORD_ID 
FROM 
    MY_TABLE 
WHERE 
    RECORD_CREATED >= '20140801' 
ORDER BY 
    RECORD_ID 

SELECT TOP 1 
    RECORD_ID 
FROM 
    MY_TABLE 
WHERE 
    RECORD_CREATED >= '20140801' 
ORDER BY 
    RECORD_CREATED 

执行时间分别为1630ms和6ms。

请指教。

P.S.:由于环境的安全策略,我看不到执行计划或使用SQL Profiler

+0

第二个只是一个直接索引寻求。如果索引不覆盖,则读取第一行大于或等于查找点以及可能的单个查找。在你的情况下,索引将被覆盖,因为NCI总是包含CI密钥,因此不需要查找。 – 2014-09-10 18:39:26

+0

@马丁史密斯,我真的很抱歉,但我完全不理解你的评论。你能解释一下吗?答案也是受欢迎的。 – 2014-09-10 19:26:28

+0

我不会在PC上提交答案,因为我不在PC上。通常'RECORD_CREATED> ='20140801'可以通过范围寻找来满足。找到索引中的相关点,然后一起扫描。因为您只想索引顺序中的前1位,SQL Server可以在读取第一行时立即停止范围查找。您的选择列表实际上位于不同的列'record_id'上,但它也静默地包含在非聚集索引中,因为它是聚簇索引键。 – 2014-09-10 19:32:43

回答

2

SQL Server有几个关于如何执行此查询的选择。它可能开始排序所有项目,利用您提到的索引,然后通过筛选出任何不匹配WHERE子句的项目。但是,通常要减少与第一个一起使用的数据集的大小,因此您不必排序尽可能多的项目。

因此,SQL Server最有可能选择首先执行WHERE过滤器。当它这样做时,它最有可能通过使用RECORD_CREATED上的非唯一非聚集索引来跳过RECORD_CREATED小于'20140801'的所有项目,然后获取所有项目。

此时,所有项目都按照它们在RECORD_CREATED索引中找到的顺序进行了预先排序,因此第二个查询不需要额外的努力,但第一个查询必须对记录执行排序已被选中。

+0

如果发动机决定先排序,该怎么办?其他选项会更快吗?我想不是,第二种选择会更快,对吗? – 2014-09-10 19:31:48

+0

在数据库优化方面,我不是向导,但我猜这取决于一些因素,例如表中有多少项与WHERE子句匹配。 – StriplingWarrior 2014-09-10 19:40:31

相关问题