2012-07-12 146 views
1

我有兩個表,我想加入,他們都有索引我想加入的列。是否仍然有效?

QUERY 1

SELECT * FROM [A] INNER JOIN [B] ON [A].F = [B].F; 

QUERY 2

SELECT * FROM (SELECT * FROM [A]) [A1] INNER JOIN (SELECT * FROM B) [B1] ON [A1].F=[B1].F 

所述第一查詢清楚地將利用索引,關於什麼第二個? 在括號中的兩個選擇語句執行後,然後加入會發生,但我的猜測是索引無助於加快查詢,因爲它幾乎是一個新表..

+2

實際上,兩個查詢都返回相同的結果。 兩者都應該使用索引(檢查查詢計劃) 真正的問題是爲什麼你會想要使用query2? – Jimbo 2012-07-12 20:09:11

+0

「FROM [A]」和「FROM(SELECT * FROM [A])As [A]」是一回事。 – RBarryYoung 2012-07-12 20:23:17

+0

@Jimbo,我將它抽象爲一個更簡單的例子。因爲這兩個子查詢是在不同階段構建的,然後組合起來形成一個更大的查詢,這就是爲什麼我有查詢2而不是查詢1 – y62wang 2012-07-12 21:28:20

回答

5

不執行查詢這麼徹底爲你的建議,其中內查詢第一,那麼他們的執行結果與外部查詢結合使用。優化器會接受您的查詢,並會查看許多可能的方式,通過各種連接命令,索引用法等獲取數據,並提出一個感覺足夠優化的計劃。

如果你執行兩個查詢並查看它們各自的執行計劃,我想你會發現它們使用完全相同的執行計劃。

下面是一個簡單的相同概念的例子。我創建了我的模式,如下所示:

CREATE TABLE A (id int, value int) 
CREATE TABLE B (id int, value int) 

INSERT INTO A (id, value) 
VALUES (1,900),(2,800),(3,700),(4,600) 

INSERT INTO B (id, value) 
VALUES (2,800),(3,700),(4,600),(5,500) 

CREATE CLUSTERED INDEX IX_A ON A (id) 
CREATE CLUSTERED INDEX IX_B ON B (id) 

然後運行您提供的查詢。

SELECT * FROM A INNER JOIN B ON A.id = B.id 
SELECT * FROM (SELECT * FROM A) A1 INNER JOIN (SELECT * FROM B) B1 ON A1.id = B1.id 

中生成的計劃是這樣的:

enter image description here

其中,你可以看到,無論是利用指數。

+0

這是更復雜查詢的情況嗎?如果我有兩個複雜的子查詢與他們內部的聯合/條件,當我對這兩個子查詢執行連接時,我不太確定它是否會給出使用索引的相同執行計劃。所以我只能依靠優化器來做出這個決定? – y62wang 2012-07-12 21:33:03

+0

是的,無論查詢有多複雜,它都由優化器決定如何獲取數據。除非您決定使用提示,但通常不推薦用於生產環境。 – 2012-07-13 12:28:22

4

機會很高, SQL Server查詢優化器將能夠檢測到查詢2實際上與查詢1相同並使用相同的索引方法。

是否發生這種情況取決於很多因素:您的表格設計,表格統計信息,查詢的複雜程度等。如果您想確切地知道,請讓SQL Server查詢分析器向您顯示執行計劃 。這裏有一些鏈接,以幫助您入門:

2

SQL Server使用predicate pushing(又名謂詞下推)將查詢條件儘可能移向源表。它不會按照你加括號的順序來做任何事情。優化器使用複雜規則 - 本質上是一種幾何 - 確定查詢的,並根據需要重新調整對數據的訪問權限,以獲得最佳性能,同時仍返回相同的最終集合您的查詢邏輯需要的數據。

當查詢變得越來越複雜時,就是這一點,優化程序無法詳盡搜索所有可能的執行計劃,最終可能會導致次優。然而,你幾乎可以假設像你這樣簡單的案例總是要被「透視」並優化掉。

所以答案是,彷彿兩個查詢合併你應該得到同樣出色的表現。現在,如果你是加盟的值是複合材料,這是他們的計算或級聯的結果,那麼你幾乎可以肯定不會讓你想,這將使該指數有用的謂語推,因爲服務器將不會或不能根據部分字符串或執行反向算術或其他操作之後進行查找。

我建議,今後,問這樣的問題在這裏之前,你只需檢查執行計劃爲自己驗證它使用的指標?你可以通過一些實驗來回答你自己的問題。如果你仍然有問題,然後來郵寄,但同時嘗試做一些自己的研究,作爲尊重正在幫助你的人的一種信號。

要查看執行計劃,請在SQL Server Management Studio(2005或更高版本)或SQL查詢分析器(SQL 2000)中單擊菜單欄上的「顯示執行計劃」按鈕,運行查詢並切換到底部的選項卡顯示執行計劃的圖形版本。有些小玩意兒將鼠標懸停在各個部分上會很快顯示哪些索引正在哪些表上使用。

但是,如果事情並不像你期望的那樣,不會自動認爲服務器是犯了一個錯誤。它可能會決定不使用索引掃描主表的成本更低 - 並且它幾乎總是正確的。有很多原因可以使得掃描成本更低,其中一個是非常小的表格,另一個是服務器統計推測它將不得不返回的行數超過表格的很大一部分。

0

這兩個查詢相同。第二個查詢將在轉換過程中與第一個查詢相同。

不過,如果你有特殊的要求,我會建議你把整個code.Then這將是很容易回答你的問題。