【问题标题】:WHERE and JOIN order of operationWHERE和JOIN操作顺序
【发布时间】:2011-04-27 00:14:29
【问题描述】:

我的问题与SQL order of operations 类似,但略有不同,所以我认为这样问是公平的。

我正在使用 Teradata。我有 2 张桌子:table1table2

table1 只有一个 id 列。
table2 有以下列:idval

我可能错了,但我认为这两个陈述给出了相同的结果。

声明 1.

SELECT table1.id, table2.val
FROM table1
INNER  JOIN table2
ON table1.id = table2.id
WHERE table2.val<100

声明 2。

SELECT table1.id, table3.val
FROM table1
INNER JOIN (
    SELECT *
    FROM table2
    WHERE val<100
)  table3
ON table1.id=table3.id

我的问题是,查询优化器是否足够聪明
- 先执行 WHERE 子句,然后在语句 1 中执行 JOIN
- 知道语句 2 中实际上不需要表 3

我对 SQL 很陌生,所以如果我有什么误解,请指教。

【问题讨论】:

  • 我原以为查询优化器会为两者提供相同的计划。尝试运行 EXPLAIN 计划进行验证。

标签: sql teradata


【解决方案1】:

这取决于很多事情(表大小、索引、键分布等),您应该只检查执行计划:

你不说是哪个数据库,但这里有一些方法:
MySql EXPLAIN
SQL Server SET SHOWPLAN_ALL (Transact-SQL)
Oracle EXPLAIN PLAN

what is explain in teradata?
Teradata Capture and compare plans faster with Visual Explain and XML plan logging

【讨论】:

  • 我很确定 Russell 确实说过哪个数据库。就是这个en.wikipedia.org/wiki/Teradata
  • @Conrad Frix ,谢谢阅读,我已经添加了链接
【解决方案2】:

根据相关表的统计信息和索引的可用性,优化器中的查询重写机制可能会或可能不会在扫描Table1 之前选择扫描Table2 以查找val &lt; 100 的记录。

在某些情况下,根据数据人口统计、连接、索引和统计信息,您可能会发现优化器并没有在您认为应该删除查询计划中的记录时。即使您有一个派生表,例如您的示例中的表。您可以通过在派生表中简单地放置一个 GROUP BY 来强制优化器处理派生表。然后,优化器有义务先解决 GROUP BY 聚合,然后才能考虑解决示例中两个表之间的连接问题。

SELECT table1.id, table3.val
FROM table1
INNER JOIN (
    SELECT table2.id, tabl2.val
    FROM table2
    WHERE val<100
    GROUP BY 1,2
)  table3
ON table1.id=table3.id

这并不是说您的标准方法应该是在整个代码中运行它。当我有一个查询计划时,这通常是我最后的手段之一,该计划根本没有在计划中足够早地消除无关记录,并导致过多的数据被扫描并通过各种 SPOOL 文件携带。当您遇到这种情况时,这只是您可以将其放入工具包中的一种技术。

查询重写机制不断从一个版本更新到下一个版本,有关其工作原理的详细信息,请参阅 Teradata 13.0 的 SQL Transaction Processing Manual

【讨论】:

    【解决方案3】:

    除非我遗漏了什么,否则为什么还需要 Table1?

    只查询Table2

    Select id, val  
    From table2  
    WHERE val<100 
    

    或者您是否使用 table1 中的行作为过滤器?即,表 1 是否仅包含表 2 中 Id 的子集?

    如果是这样,那么这也可以......

     Select id, val  
     From table2  
     Where val<100 
       And id In (Select id 
                  From table1)
    

    但要回答您的问题,是的,查询优化器应该足够智能,能够找出执行将逻辑指令转换为物理结果所需步骤的最佳顺序。它使用数据库在每个表上维护的存储统计信息来确定要做什么(例如使用什么类型的连接逻辑),以及执行操作的顺序以最小化磁盘 IO 和处理成本。

    【讨论】:

    • 好吧,他正在进行内部连接,因此他将结果集限制在两个表中都存在值的位置。
    【解决方案4】:

    第一季度。先执行 WHERE 子句,然后在 Statement 1 中执行 JOIN

    问题是,如果你切换内部连接的顺序,即table2 INNER JOIN table1,那么我猜想WHERE子句可以在JOIN操作之前处理,在准备阶段。但是,我想即使您不更改原始查询,优化器也应该能够切换它们的顺序,如果它认为连接操作在获取整行时成本太高,那么它将首先应用 WHERE。只是我的猜测。

    第二季度。知道语句 2 中实际上不需要表 3

    Teradata 将以派生表是必需的方式解释您的第二个查询,因此它将继续处理涉及表 3 的操作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-01-20
      • 2023-01-10
      • 1970-01-01
      • 1970-01-01
      • 2022-12-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多