sql-server – 为什么添加TOP 1会显着恶化性能?

前端之家收集整理的这篇文章主要介绍了sql-server – 为什么添加TOP 1会显着恶化性能?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有一个相当简单的查询
SELECT TOP 1 dc.DOCUMENT_ID,dc.COPIES,dc.REQUESTOR,dc.D_ID,cj.FILE_NUMBER
FROM DOCUMENT_QUEUE dc
JOIN CORRESPONDENCE_JOURNAL cj
    ON dc.DOCUMENT_ID = cj.DOCUMENT_ID
WHERE dc.QUEUE_DATE <= GETDATE()
  AND dc.PRINT_LOCATION = 2
ORDER BY cj.FILE_NUMBER

这给了我可怕的表现(从来没有费心等待它完成).查询计划如下所示:

但是,如果我删除TOP 1,我会得到一个看起来像这样的计划,并在1-2秒内运行:

正确的PK&索引如下.

TOP 1改变了查询计划的事实并没有让我感到惊讶,我只是有点惊讶它让它变得更糟.

注意:我已经阅读了post的结果并理解了行目标等的概念.我很好奇的是如何更改查询以便它使用更好的计划.目前我正在将数据转储到临时表中,然后从中拉出第一行.我想知道是否有更好的方法.

编辑对于在此之后阅读此内容的人,这里有一些额外的信息.

> Document_Queue – PK / CI是D_ID,它有~5k行.
> Correspondence_Journal – PK / CI是FILE_NUMBER,CORRESPONDENCE_ID,它有~1.4 mil的行.

当我开始时没有其他索引.我在Correspondence_Journal(Document_Id,File_Number)上找到了一个

解决方法

尝试强制加入 hash *
SELECT TOP 1 
       dc.DOCUMENT_ID,cj.FILE_NUMBER
FROM DOCUMENT_QUEUE dc
INNER HASH JOIN CORRESPONDENCE_JOURNAL cj
        ON dc.DOCUMENT_ID = cj.DOCUMENT_ID
       AND dc.QUEUE_DATE <= GETDATE()
       AND dc.PRINT_LOCATION = 2
ORDER BY cj.FILE_NUMBER

优化器可能认为前一个循环会更好,而这种情况有意义,但实际上它在这里不起作用.这里只是一个猜测,但也许该假脱机的估计成本已关闭 – 它使用TEMPDB – 您的TEMPDB可能表现不佳.

*注意join hints,因为它们强制计划表访问顺序与查询中表的写入顺序相匹配(就像指定了OPTION(FORCE ORDER)).从文档链接

这可能不会在示例中产生任何不良影响,但总的来说,它可能会很好. FORCE ORDER(隐含或显式)是一个非常强大的提示,超出了强制执行的顺序;它阻止了广泛的优化器技术的应用,包括部分聚合和重新排序.

在适当的情况下,OPTION(HASH JOIN)查询提示可能不那么具有侵入性,因为这并不意味着FORCE ORDER.但是,它确实适用于查询中的所有联接.其他解决方案可用.

原文链接:https://www.f2er.com/mssql/80164.html

猜你在找的MsSQL相关文章