我的问题与此相似 SQL操作顺序 但是有一点扭曲,所以我认为这很公平。

我正在使用Teradata。我有2张桌子: table1, table2.

table1 只有一个 id 柱子。
table2 具有以下列: id, val

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

声明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中加入
- 知道说明2中实际上不需要表3

我是SQL的新手,所以如果我误会任何事情,请教育我。

有帮助吗?

解决方案

这将取决于许多事情(表尺寸,索引,密钥分布等),您应该只检查执行计划:

您不会说哪个数据库,但以下是一些方法:
MySQL解释
SQL Server SET SHAWPLAN_ALL(TRANSACT-SQL)
Oracle解释计划

Teradata中的解释是什么?
Teradata捕获和比较计划与视觉解释和XML计划记录更快

其他提示

根据有关表的统计数据和索引的可用性,优化器中的查询重写机制可能会或可能不会选择扫描 Table2 用于记录 val < 100 扫描之前 Table1.

在某些情况下,基于数据人口统计数据,连接,索引和统计信息,您可能会发现,当您认为应该使用时,优化器不会消除查询计划中的记录。即使您有一个派生的表,例如示例中的桌子。您可以强迫优化器通过简单地将组放入派生表中来处理派生表。然后,优化器有义务通过汇总来解决该组,然后才能考虑在示例中解决两个表之间的联接。

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

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

查询重写机制正在不断从一个版本更新到下一个版本,有关其工作方式的详细信息可以在 SQL交易处理手册 对于Teradata 13.0。

除非我错过了什么,为什么您甚至需要table1?

只是查询table2

Select id, val  
From table2  
WHERE val<100 

还是您使用表1中的行作为过滤器?即,table1仅copnain copnain table2中的ID子集?

如果是这样,那么这也将有效...

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

但是要回答您的问题,是的,查询优化器应该足够智能,以找出最佳顺序,以执行将逻辑指令转化为物理结果所需的步骤。它使用数据库在每个表上维护的统计统计信息来确定该执行的操作(例如,使用哪种类型的联接逻辑)为WEKLL,作为为了最大程度地减少磁盘iOS和处理成本而执行操作的顺序。

Q1。首先执行Where子句,然后在语句1中加入

事实是,如果您切换内在加入的顺序,即IE Table2 Inner Join Table1,那么我猜在准备阶段加入操作之前可以在哪里处理子句。但是,我想即使您不更改原始查询,优化器也应该能够切换其订单,如果它认为连接操作会在获取整个行时太昂贵,因此它将适用于首先的位置。只是我的猜测。

Q2。知道说明2中实际上不需要表3

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top