2011-06-23 63 views
3

我有一個存儲過程,它連接多個表並從中選擇字段。其中一張桌子是臨時桌子。導致主要性能問題的SQL選擇字段

SELECT 
    a.Field1, 
    a.Field2, 
    b.Field3, 
    b.Field4, 
    c.Field5 
FROM table1 a 
    LEFT JOIN #table2 b ON a.Field1 = b.Field1 
    INNER JOIN table3 c ON a.Field1 = c.Field1 

以上需要10+分鐘,但是如果我在選擇註釋掉兩個b領域同時保留它在幾秒鐘內運行的地方加入。

我已經將這一過程簡化爲同樣的行爲。執行計劃也幾乎完全相同。

任何幫助表示讚賞。

+0

這兩個字段的數據類型是什麼? – HLGEM

+0

'char(1)'。這是「Y」或「N」。 –

+0

那麼,我吹噓自己是廣泛領域的理論,因此需要更長的時間來傳遞數據。但它確實解釋了爲什麼索引可能沒有幫助,沒有足夠的特異性。 – HLGEM

回答

1

有多少行的臨時表,而且是「字段2」中的臨時表的主鍵?

如果您沒有從左連接的右表中選擇任何行,並且連接是主鍵(或可能是唯一鍵),並且您沒有引用來自右表的列,則SQL Server可以避免必須訪問臨時表(因爲存在或不存在連接行對最終結果沒有影響):

示例。表設置:

create table T1 (
    ID int not null primary key, 
    Col1 varchar(10) not null 
) 
go 
insert into T1 (ID,Col1) 
select 1,'a' union all 
select 2,'b' union all 
select 3,'c' 
go 
create table #t2 (
    ID int not null primary key, 
    Col2 varchar(10) not null 
) 
go 
insert into #t2 (ID,Col2) 
select 1,'d' union all 
select 2,'e' union all 
select 4,'f' 
go 
create table #t3 (
    ID int not null, 
    Col3 varchar(10) not null 
) 
go 
insert into #t3 (ID,Col3) 
select 1,'d' union all 
select 2,'e' union all 
select 1,'f' 

而且查詢:

select T1.ID,T1.Col1 from T1 left join #t2 t2 on T1.ID = t2.ID 
select T1.ID,T1.Col1,t2.Col2 from T1 left join #t2 t2 on T1.ID = t2.ID 
select T1.ID,T1.Col1 from T1 left join #t3 t3 on T1.ID = t3.ID 
select T1.ID,T1.Col1,t3.Col2 from T1 left join #t2 t3 on T1.ID = t3.ID 

但在所有的第一個查詢,連接發生預期。但是由於#t2中存在或不存在行不會影響第一個查詢的最終結果,因此它會避免完全執行連接。

但是,如果它不是這樣的(我希望它是在查詢計劃中的明顯差異)<我有點難住。

+0

這是主鍵!太感謝了。我將PK添加到臨時表中,並且它的指數快速增長。 –

+0

@Dustin - 好吧,這很尷尬 - 提到PK幾乎是我的答案肉,但我很高興這有助於激發一些東西。 –

1

您是否嘗試過反轉連接? (雖然你缺少一個在示例查詢加入爲表C條件)

SELECT 
    a.Field1, 
    a.Field2, 
    b.Field3, 
    b.Field4, 
    c.Field5 
FROM table1 a 
    INNER JOIN table3 c 
    LEFT JOIN #table2 b ON a.Field1 = b.Field1 
+0

對不起,錯字,因爲這只是一個例子。 JOIN順序應該不重要,並且還有大約10個其他連接。我已經縮小到選擇範圍。 –

0

我會嘗試與包括列添加索引,以#table2並看看是否有幫助:

CREATE NONCLUSTERED INDEX IX_table2 
    ON #table2 (Field1) 
    INCLUDE (Field3, Field4); 
+0

我已經嘗試過,沒有運氣。它既沒有幫助也沒有受傷。 –

0

如何運行查詢分兩部分。儘可能限制第一部分,然後僅對已過濾的集合進行外連接。

SELECT a.Field1, 
      a.Field2,  
      b.Field3,  
      c.Field5 
INTO #t 
FROM table1 a 
    INNER JOIN table3 c ON a.Field1 = c.Field1 

SELECT t.Field1, 
     t.field2, 
     b.field3, 
     b.field4, 
     t.field5 
FROM #t t 
    LEFT OUTER JOIN #table2 b ON t.Field1 = b.Field1    
0
select * into #temp from table1 
select * into #temp1 from table2 
select * into #temp2 from table3 


SELECT 
    a.Field1, 
    a.Field2, 
    b.Field3, 
    b.Field4, 
    c.Field5 
FROM #temp a 
    LEFT JOIN #temp1 b ON a.Field1 = b.Field1 
    INNER JOIN #temp2 c ON a.Field1 = c.Field1 



if(Object_Id('TempDB..#temp') Is Not Null) 
Begin 
    Drop table #temp 
End 
if(Object_Id('TempDB..#temp1') Is Not Null) 
Begin 
    Drop table #temp1 
End 
if(Object_Id('TempDB..#temp2') Is Not Null) 
Begin 
    Drop table #temp2 
End