AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 24832
Accepted
David
David
Asked: 2012-09-25 11:08:09 +0800 CST2012-09-25 11:08:09 +0800 CST 2012-09-25 11:08:09 +0800 CST

TOP 如何(以及为什么)影响执行计划?

  • 772

对于我正在尝试优化的中等复杂查询,我注意到删除TOP n子句会更改执行计划。我会猜到,当查询包含TOP n数据库引擎时会忽略该TOP子句运行查询,然后最后将该结果集缩小到请求的n行数。图形执行计划似乎表明情况就是这样——TOP是“最后”一步。但似乎还有更多的事情发生。

我的问题是,TOP n 子句如何(以及为什么)影响查询的执行计划?

这是我的情况的简化版本:

该查询匹配两个表 A 和 B 中的行。

如果没有该TOP子句,优化器估计表 A 中将有 19k 行,表 B 中将有 46k 行。返回的实际行数是 A 的 16k 和 B 的 13k。哈希匹配用于连接这两个结果集以获得总共 69 行(然后应用排序)。这个查询发生得很快。

当我添加TOP 1001优化器时不使用哈希匹配;相反,它首先对表 A 中的结果进行排序(相同的估计/实际为 19k/16k)并针对表 B 执行嵌套循环。表 B 的估计行数现在为 1,奇怪的是TOP n直接影响针对 B 的估计执行次数(索引搜索)——它似乎总是2n+1,或者在我的情况下是 2003 。如果我改变,这个估计会相应地改变TOP n。当然,由于这是一个嵌套连接,实际执行次数为 16k(表 A 中的行数),这会减慢查询速度。

查询有一个ORDER BY子句。在计划中发生这种排序的位置添加TOP更改,但我更关心它如何影响对表 B 执行索引搜索的次数。

实际情况要复杂一些,但这抓住了基本的想法/行为。两个表都使用索引搜索进行搜索。这是 SQL Server 2008 R2 企业版。

sql-server query-performance
  • 2 2 个回答
  • 11557 Views

2 个回答

  • Voted
  1. Best Answer
    Paul White
    2012-09-25T23:10:43+08:002012-09-25T23:10:43+08:00

    我会猜到,当查询包含 TOP n 时,数据库引擎会运行查询而忽略 TOP 子句,然后最后将该结果集缩小到请求的 n 行数。图形执行计划似乎表明情况就是这样——TOP 是“最后”一步。但似乎还有更多的事情发生。

    上述措辞的方式让我认为您可能对查询的执行方式有一个不正确的心理画面。查询计划中的运算符不是一个步骤(前一步的完整结果集由下一个步骤评估。

    SQL Server 使用流水线执行模型,其中每个运算符都公开Init()、GetRow()和Close()等方法。正如GetRow()名称所暗示的那样,操作员根据需要一次生成一行(根据其父操作员的要求)。这在 Books Online Logical and Physical Operators 参考中有记录,在我的博客文章Why Query Plans Run Backwards中有更多详细信息。这种一次一行的模型对于为查询执行形成合理的直觉至关重要。

    我的问题是,n 子句如何(以及为什么)TOP影响查询的执行计划?

    一些逻辑操作TOP,如半连接和FAST n 查询提示,会影响查询优化器对执行计划备选方案进行成本计算的方式。基本思想是,一个可能的计划形状可能比经过优化以返回所有行的不同计划更快地返回前n行。

    例如,索引嵌套循环连接通常是返回少量行的最快方法,尽管散列或合并连接与扫描可能在较大的集合上更有效。查询优化器对这些选择进行推理的方式是在操作逻辑树中的特定点设置行目标。

    行目标修改查询计划备选方案的成本计算方式。它的本质是优化器首先计算每个运算符的成本,就好像需要完整的结果集一样,在适当的点设置一个行目标,然后沿着计划树向下工作,估计它预计需要检查的行数以满足行目标。

    例如,逻辑TOP(10)在逻辑查询树中的特定点设置行目标 10。导致行目标的操作员成本被修改以估计他们需要生产多少行才能满足行目标。此计算可能会变得复杂,因此通过完整的示例和带注释的执行计划更容易理解所有这些。行目标可能影响的不仅仅是连接类型的选择或查找和查找是否比扫描更受欢迎。更多细节在这里。

    与往常一样,基于行目标选择的执行计划取决于优化器的推理能力和提供给它的信息质量。并非每个具有行目标的计划在实践中都会更快地生成所需的行数,但根据成本计算模型,它会。

    在行目标计划被证明不是更快的情况下,通常有一些方法可以修改查询或向优化器提供更好的信息,以便自然选择的计划是最好的。哪个选项适合您的情况当然取决于细节。行目标功能通常非常有效(尽管在并行执行计划中使用时需要注意一个错误)。

    您的特定查询和计划可能不适合在此处进行详细分析(如果您愿意,请务必提供实际的执行计划),但希望此处概述的想法能让您取得进展。

    • 44
  2. Rob Farley
    2012-09-25T16:47:10+08:002012-09-25T16:47:10+08:00

    当您使用 TOP 时,优化器看到了减少工作量的机会。如果您要求 10 行,那么很有可能它不需要消耗整个集合。因此 TOP 运算符可以被推到更远的右侧。它将继续向下一个运算符(在其右侧)请求行,直到收到足够的数据。

    您指出,如果没有 TOP,查询会在最后对数据进行排序。如果引擎可以提前知道连接将满足多少行,它可能会选择使用类似的计划,将 TOP 定位在左侧。但是由于进行哈希匹配的工作量相对较高,并且可能没有合并连接的选项,优化器可能更喜欢进一步向右过滤 TOP。

    当查询表 B 时,它一次获取一行。这就是估计值为 1 的原因。它还假设它只会在 50% 的时间内找到该行。所以它猜测它需要 2n+1 次才能找到它。

    • 12

相关问题

  • SQL Server - 使用聚集索引时如何存储数据页

  • 我需要为每种类型的查询使用单独的索引,还是一个多列索引可以工作?

  • 什么时候应该使用唯一约束而不是唯一索引?

  • 死锁的主要原因是什么,可以预防吗?

  • 如何确定是否需要或需要索引

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    如何查看 Oracle 中的数据库列表?

    • 8 个回答
  • Marko Smith

    mysql innodb_buffer_pool_size 应该有多大?

    • 4 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    从 .frm 和 .ibd 文件恢复表?

    • 10 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    如何选择每组的第一行?

    • 6 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    pedrosanta 使用 psql 列出数据库权限 2011-08-04 11:01:21 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST
  • Martin Hope
    bernd_k 什么时候应该使用唯一约束而不是唯一索引? 2011-01-05 02:32:27 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve