题
我的问题与此相似 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解释计划
其他提示
根据有关表的统计数据和索引的可用性,优化器中的查询重写机制可能会或可能不会选择扫描 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所涉及的操作。