分页结果集中的选择子查询或左外连接哪个更快

Posted

技术标签:

【中文标题】分页结果集中的选择子查询或左外连接哪个更快【英文标题】:Which is faster a select sub-query or a left outer join in a paginated result set 【发布时间】:2011-11-09 01:14:31 【问题描述】:

使用 MSSQL 查询时,从计算表中获取单个列并将其连接到结果集的最有效方法是什么。

表:mytable = mytable.col1 上的 20k 行索引,othertable = 30k 行,othertable.col1 上没有索引

内联查询 - 在 select 语句中运行查询

SELECT * FROM (
    SELECT col1, col2, col3, 
    col4 = (SELECT min(col5) FROM othertable o WHERE m.col1 = o.col1)
    row = ROW_NUMBER() OVER(ORDER BY somerow) 
    FROM mytable m
) as paged
WHERE row BETWEEN 1 AND 25

Join Query - 将我们的表加入计算表

SELECT * FROM (
    SELECT col1, col2, col3, o2.col5again
    row = ROW_NUMBER() OVER(ORDER BY somerow) 
    FROM mytable m
    JOIN (SELECT col1, min(col5) as col5again FROM othertable o GROUP BY col1) as o2 ON o2.col1 = m.col1
) as paged
WHERE row BETWEEN 1 AND 25

我的直觉是JOIN 更快。然而,在测试中,内联查询平均在 7 秒内完成,而在 MSSQL Studio 中执行其他查询则需要 30 秒以上。

    使用内联选择查询真的是注入单列的最佳方式吗? 查询优化后是否等待运行内联 SELECT() 语句,直到结果被分页,这是否可以解释运行时间的不同?

仅供参考:在我的具体示例中,我们向othertable.col1 添加了一个索引,它将查询时间减少到 0 秒,但这个问题更多地关注于 JOIN 与 SELECT() 是否更好。

【问题讨论】:

这两个都编译吗?看起来最里面的查询丢失了FROM 添加了FROM,我没有测试过这个确切的查询,因为我从我遇到的实际示例中对其进行了清理,以便在 SO 上提出一个更清晰的问题。 找出答案的最佳方法:使用set statistics time on 运行两个查询以查看它们的持续时间。您还可以运行跟踪以查看持续时间。 您不需要在第二个示例中加入子查询。只需直接加入othertable 并将您的GROUP BY 放入封闭的查询中。无论如何,查询引擎将在执行连接之前将GROUP BY 应用到othertable,并且您的查询将具有更少的级别。 这两个查询看起来将具有完全相同的查询计划。您是否检查过两者的查询计划? 【参考方案1】:

性能调优是一门艺术,它涉及理解为什么要按原样创建计划、计划中的每个部分的作用以及如何影响选择更有效的路径。

缺少覆盖索引会导致扫描(过度读取)。过多的索引会减慢您的 DUI(删除、更新和插入)。过时或缺失的统计信息将导致使用错误的连接算法和/或估计的行数不准确(这可能导致分页)。

在同一个窗口中运行两个查询并包含实际的执行计划。这将拆分计划并告诉您哪个更昂贵。它会给你缺失的索引提示。随着您在阅读计划方面的进步,您将了解如何提高查询性能。

【讨论】:

以上是关于分页结果集中的选择子查询或左外连接哪个更快的主要内容,如果未能解决你的问题,请参考以下文章

使用子查询改进 MySql 查询左外连接

内连接与左外链接的区别

左外连接,最终查询没有结果

带有子查询的左外连接?

sql的四种连接——左外连接右外连接内连接全连接

左外连接和右外连接的区别