2010-10-18 54 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中找到。