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 / 问题 / 58602
Accepted
Matthew
Matthew
Asked: 2014-02-11 09:02:42 +0800 CST2014-02-11 09:02:42 +0800 CST 2014-02-11 09:02:42 +0800 CST

我应该在 SQL Server 中嵌套依赖外部联接吗?

  • 772

我听到了关于这方面的混合信息,希望得到规范或专家的意见。

如果我有多个LEFT OUTER JOINs ,每个都依赖于最后一个,嵌套它们是否更好?

对于人为的示例,JOINtoMyParent取决于JOINto MyChild: http ://sqlfiddle.com/#!3/31022/5

SELECT
    {columns}
FROM
    MyGrandChild AS gc
LEFT OUTER JOIN
    MyChild AS c
        ON c.[Id] = gc.[ParentId]
LEFT OUTER JOIN
    MyParent AS p
        ON p.[id] = c.[ParentId]

在此处输入图像描述

与http://sqlfiddle.com/#!3/31022/7相比

SELECT
    {columns}
FROM
    MyGrandChild AS gc
LEFT OUTER JOIN
    (
    MyChild AS c            
    LEFT OUTER JOIN
        MyParent AS p
            ON p.[id] = c.[ParentId]
    )
    ON c.[Id] = gc.[ParentId]

在此处输入图像描述

如上所示,这些在 SS2k8 中产生不同的查询计划

performance sql-server-2008-r2
  • 2 2 个回答
  • 857 Views

2 个回答

  • Voted
  1. Best Answer
    Martin Smith
    2014-02-12T17:11:11+08:002014-02-12T17:11:11+08:00

    这绝对不是一个规范的答案,但我注意到对于 SQL Fiddle 中显示的嵌套循环查询计划,可以使用USE PLAN提示将查询 2 中的计划应用到查询 1,但尝试反向操作失败

    查询处理器无法生成查询计划,因为 USE PLAN 提示包含无法验证查询合法的计划。删除或替换 USE PLAN 提示。为了最大可能地强制执行成功的计划,请确认 USE PLAN 提示中提供的计划是由 SQL Server 为同一查询自动生成的计划。

    禁用优化器转换规则 ReorderLOJN会阻止先前成功的计划提示也成功。

    对更多数据的试验表明,SQL Server 当然也能够自然地转换(A LOJ B) LOJ C为A LOJ (B LOJ C),但我没有看到任何相反的证据。

    第一个查询比第二个查询执行得更好的一个非常人为的情况是

    DROP TABLE  MyGrandChild , MyChild,  MyParent
    
    CREATE TABLE MyParent
    (Id int)
    
    CREATE TABLE MyChild
    (Id int PRIMARY KEY
    ,ParentId int,
    Filler char(8000) NULL)
    
    CREATE TABLE MyGrandChild
    (Id int
    ,ParentId int)
    
    INSERT INTO MyChild
                          (Id, ParentId)
    SELECT TOP (100000) ROW_NUMBER() OVER (ORDER BY @@SPID),
                         ROW_NUMBER() OVER (ORDER BY @@SPID)    
    FROM master..spt_values  v1, master..spt_values                  
    
    INSERT INTO MyGrandChild
                          (Id, ParentId)
    OUTPUT INSERTED.Id INTO MyParent
    SELECT TOP (3000) Id, Id AS ParentId
    FROM MyChild
    ORDER BY Id
    
    SET STATISTICS IO ON;
    SET STATISTICS TIME ON;
    
    SELECT gc.Id       AS gcId,
           gc.ParentId AS gcpId,
           c.Id        AS cId,
           c.ParentId  AS cpId,
           p.Id        AS pId
    FROM   MyGrandChild AS gc
           LEFT OUTER JOIN MyChild AS c
             ON c.[Id] = gc.[ParentId]
           LEFT OUTER JOIN MyParent AS p
             ON p.[Id] = c.[ParentId]
    
    SELECT gc.Id       AS gcId,
           gc.ParentId AS gcpId,
           c.Id        AS cId,
           c.ParentId  AS cpId,
           p.Id        AS pId
    FROM   MyGrandChild AS gc
           LEFT OUTER JOIN( MyChild AS c
                            LEFT OUTER JOIN MyParent AS p
                              ON p.[Id] = c.[ParentId])
             ON c.[Id] = gc.[ParentId] 
    

    哪个给出计划

    在此处输入图像描述

    对我来说,查询 1 的运行时间为 108 毫秒,而查询 2 的运行时间为 1,163 毫秒。

    查询 1

    Table 'Worktable'. Scan count 0, logical reads 0 
    Table 'MyChild'. Scan count 0, logical reads 9196
    Table 'MyGrandChild'. Scan count 1, logical reads 7
    Table 'MyParent'. Scan count 1, logical reads 5
    

    查询 2

    Table 'MyParent'. Scan count 1, logical reads 15000
    Table 'MyChild'. Scan count 0, logical reads 9000 
    Table 'MyGrandChild'. Scan count 1, logical reads 7
    

    因此,可能会暂时假设第一个(“未嵌套”)语法可能是有益的,因为它允许考虑更多潜在的连接顺序,但我还没有进行足够详尽的测试以对此作为一般规则充满信心。

    完全有可能提出查询 2 执行得更好的反例。尝试两者并查看执行计划。

    • 3
  2. Anup Shah
    2014-02-11T11:00:13+08:002014-02-11T11:00:13+08:00

    没有这种称为“嵌套连接”的连接类型。这是编写 JOIN 的另一种变体,可能是为了便于阅读。您可以将它们视为仅用于理解目的的“子查询”。

    如果您更关心代码的可读性,那么我的看法是,他们可以授予什么是个人的选择。

    如果您关心查询的性能,并且查询中未使用“Force JOIN ORDER”提示,那么使用“Nested Join”或“All Outer Join”编写查询都没有关系。SQL 服务器根据连接两个表和/或结果的成本得出顺序。SQL Server 一次只在两组数据之间进行 JOIN。

    事实上,想象一下,如果 SQL Server 决定执行第二部分“MyChild AS c LEFT OUTER JOIN MyParent AS p ON p.[id] = c.[ParentId]”,那么在第二种方式“嵌套连接”中,这些表会发生拥有将在 NEXT LEFT JOIN 中丢弃的行。在那种情况下,SQL Server 花费了不必要的资源来执行这两个 OUTER JOIN 并将该结果传递给下一个 JOIN。

    您也可以在此处查看类似的问题并进行适当的回答。 了解“嵌套连接”语法

    • -1

相关问题

  • 使用存储过程处理数据与在检索后将其输入函数相比是否有性能提升?

  • 您如何针对繁重的 InnoDB 工作负载调整 MySQL?

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

  • 我在哪里可以找到mysql慢日志?

  • 如何优化大型数据库的 mysqldump?

Sidebar

Stats

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

    连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目

    • 12 个回答
  • Marko Smith

    如何让sqlplus的输出出现在一行中?

    • 3 个回答
  • Marko Smith

    选择具有最大日期或最晚日期的日期

    • 3 个回答
  • Marko Smith

    如何列出 PostgreSQL 中的所有模式?

    • 4 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

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

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

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

    • 4 个回答
  • Marko Smith

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

    • 7 个回答
  • Martin Hope
    Jin 连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane 如何列出 PostgreSQL 中的所有模式? 2013-04-16 11:19:16 +0800 CST
  • 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
    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

热门标签

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