2010-10-18 74 views
10

我的问题类似于这个SQL order of operations但有一点麻烦,所以我认为这是公平的问题。WHERE和JOIN操作顺序

我正在使用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以后加入
- 知道表3在报表2中实际上并不需要

我对SQL很陌生,所以请教我如果我误解任何东西。

+1

我还以为查询优化器会拿出两个相同的计划。尽管运行'EXPLAIN'计划来验证。 – 2010-10-18 15:23:23

回答

4

这将取决于许多许多事情(表大小,索引,密钥分发等),你应该检查执行计划:

你不说哪个数据库,但这里有一些方法:
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

+0

我很确定罗素确实说过哪个数据库。它的这一个http://en.wikipedia.org/wiki/Teradata – 2010-10-18 15:32:37

+0

@Conrad Frix,感谢阅读它的正确的过去,我已经添加了链接 – 2010-10-18 15:43:42

0

除非我错过了什么,为什么你甚至需要Table1?

只是查询表2

Select id, val 
From table2 
WHERE val<100 

或者您使用的是排在表1的过滤器?即,table1只是在表2中复制了一个ID的子集?

如果是这样,那么这将工作以及...

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

但是,为了回答你的问题,是查询优化器应该是足够的智能,找出在其中执行的必要步骤的最佳顺序将您的逻辑指令转换为物理结果。它使用数据库在每个表上维护的统计数据来确定要执行的操作(例如,使用何种类型的连接逻辑),以便按照执行操作的顺序执行操作,以最大限度地减少磁盘IO和处理成本。

+3

嗯,他正在做一个内部连接,所以他将他的结果集限制在两个表中的值存在的位置。 – JNK 2010-10-18 15:23:23

0

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

问题是,如果切换内部连接的顺序,即table2 INNER JOIN table1,那么我猜WHERE子句可以在JOIN操作之前处理,在准备阶段。不过,我想,即使你不改变原来的查询,优化器应该能够切换它们的顺序,如果它认为联合操作将与取整排太贵,所以它将应用WHERE第一。只是我的猜测。

Q2。知道,表3实际上并不需要声明2

的Teradata将解释这样的方式你的第二个查询派生表是必要的,所以它将继续处理表3介入操作。

2

根据统计数据和指标有问题的表的可用性优化查询重写机制将可能会或可能不会选择在那里val < 100扫描Table1之前扫描Table2备案。

在某些情况下,根据人口统计数据,连接,检索和统计你会发现,优化没有消除查询计划的记录,当你觉得它应该。即使你有一个派生表,例如你的例子中的派生表。您可以强制优化器通过简单地将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 

这并不是说你的标准方法应该是通过你的代码运行。这通常是我最后的度假胜地之一,当我有一个根本不消除无关的记录足够早在计划和结果过多的数据进行扫描,并通过各种假脱机文件随身携带查询计划。当你遇到这种情况时,这只是一种你可以放在工具箱中的技巧。

查询重写机制不断从一个版本更新到下一个版本,有关它如何工作的详细信息可以在Teradata 13.0的SQL Transaction Processing Manual中找到。