2011-05-09 22 views
2

這更像是一個設計問題,但也與SQL優化有關。改進查詢設計以提高性能

我的項目必須將大量記錄導入數據庫(超過10萬條記錄)。同時,該項目有邏輯檢查每個記錄以確保它符合可配置的標準。然後它會將該記錄標記爲沒有警告或在數據庫中有警告。插入和警告檢查在一個導入過程中完成。

對於每個標準,它必須查詢數據庫。查詢需要加入其他兩個表,有時添加額外的嵌套查詢的條件內,如

select * from TableA a 
    join TableB on ... 
    join TableC on ... 
where 
    (select count(*) from TableA 
where TableA.Field = Bla) > 100 

雖然查詢需要不明顯時間,查詢整個記錄集的花費相當量的時間,其可以是4 - 在服務器上5個小時。特別是如果有很多標準,最後項目將停止運行導入和回滾。

我試着將「SELECT * FROM」改爲「SELECT TableA.ID FROM」,但它似乎根本沒有任何效果。有沒有更好的設計來改善這個過程的性能?

回答

1

如何創建一個臨時表(或多個)來存儲子查詢的聚合結果,然後索引那些覆蓋索引的/。

從上面的代碼中,我們將在TableA.Field1上創建一個臨時表分組,幷包括一個計數,然後在Field1上的索引theCount。在SQL Server上最快的方法將被:

select * from TableA a 
    join TableB on ... 
    join TableC on ... 
    join (select Field1 from #temp1 where theCount > 100) t on... 

這部作品的原因是,我們正在做兩次同樣的伎倆。

首先,我們預先聚合到臨時表中,這是一個簡單的操作,非常容易讓SQL Server優化。所以我們採取了一些問題,並以優化的方式解決。

然後我們通過連接到子查詢來重複這個技巧,將過濾器放入子查詢中,以便連接充當過濾器。

+0

我應該在哪裏製作臨時表? 「(從TableA選擇count(*),其中TableA.Field1 = Bla和TableA.Field2 = Blaa和...)」查詢也來自數據庫,所以我必須找出一種方法將其轉換爲臨時表。 – newguy 2011-05-09 05:53:09

+0

我假設你正在分階段進行這項工作。首先,將100k行加載到「收件箱」表或登臺表中。接下來,您將通過一個或多個步驟從該表中拉出數據,以便將數據傳輸到最終目的地。因此,可以在存儲過程或應用程序代碼中創建臨時表。 – 2011-05-09 11:51:41

0

我建議你一起批量處理你的記錄(每次500個左右),然後將它發送到一個可以進行計算的存儲過程。

在那裏使用簡單的語句而不是連接。這也節省了。這link也可能有幫助。