2012-02-09 47 views
2

有一箇舊的SSIS包,每天都會從Oracle向我們的Sql Server數據庫提取大量數據。數據被插入到一個非規範化的數據庫中,並且我正在處理一個存儲過程來選擇這些數據,並將其插入到規範化數據庫中。 Oracle數據庫過度標準化,所以我寫的查詢最終有12個內部連接來獲取我需要的所有列。另一個問題是我正在處理大量的數據。我選擇的一張桌子有超過1200萬條記錄。這是我的查詢:處理大量數據,並在SQL Server 2008中處理12個內部連接的查詢

Declare @MewLive Table 
(

UPC_NUMBER VARCHAR(50), 
ITEM_NUMBER VARCHAR(50), 
STYLE_CODE VARCHAR(20), 
COLOR VARCHAR(8), 
SIZE VARCHAR(8), 
UPC_TYPE INT, 
LONG_DESC VARCHAR(120), 
LOCATION_CODE VARCHAR(20), 
TOTAL_ON_HAND_RETAIL NUMERIC(14,0), 
VENDOR_CODE VARCHAR(20), 
CURRENT_RETAIL NUMERIC(14,2) 


) 

INSERT INTO @MewLive(UPC_NUMBER,ITEM_NUMBER,STYLE_CODE,COLOR,[SIZE],UPC_TYPE,LONG_DESC,LOCATION_CODE,TOTAL_ON_HAND_RETAIL,VENDOR_CODE,CURRENT_RETAIL) 
SELECT  U.UPC_NUMBER, REPLACE(ST.STYLE_CODE, '.', '') 
         + '-' + SC.SHORT_DESC + '-' + REPLACE(SM.PRIM_SIZE_LABEL, '.', '') AS ItemNumber, 
         REPLACE(ST.STYLE_CODE, '.', '') AS Style_Code, SC.SHORT_DESC AS Color, 
         REPLACE(SM.PRIM_SIZE_LABEL, '.', '') AS Size, U.UPC_TYPE, ST.LONG_DESC, L.LOCATION_CODE, 
         IB.TOTAL_ON_HAND_RETAIL, V.VENDOR_CODE, SD.CURRENT_RETAIL 
FROM   MewLive.dbo.STYLE AS ST INNER JOIN 
         MewLive.dbo.SKU AS SK ON ST.STYLE_ID = SK.STYLE_ID INNER JOIN 
         MewLive.dbo.UPC AS U ON SK.SKU_ID = U.SKU_ID INNER JOIN 
         MewLive.dbo.IB_INVENTORY_TOTAL AS IB ON SK.SKU_ID = IB.SKU_ID INNER JOIN 
         MewLive.dbo.LOCATION AS L ON IB.LOCATION_ID = L.LOCATION_ID INNER JOIN 
         MewLive.dbo.STYLE_COLOR AS SC ON ST.STYLE_ID = SC.STYLE_ID INNER JOIN 
         MewLive.dbo.COLOR AS C ON SC.COLOR_ID = C.COLOR_ID INNER JOIN 
         MewLive.dbo.STYLE_SIZE AS SS ON ST.STYLE_ID = SS.STYLE_ID INNER JOIN 
         MewLive.dbo.SIZE_MASTER AS SM ON SS.SIZE_MASTER_ID = SM.SIZE_MASTER_ID INNER JOIN 
         MewLive.dbo.STYLE_VENDOR AS SV ON ST.STYLE_ID = SV.STYLE_ID INNER JOIN 
         MewLive.dbo.VENDOR AS V ON SV.VENDOR_ID = V.VENDOR_ID INNER JOIN 
         MewLive.dbo.STYLE_DETAIL AS SD ON ST.STYLE_ID = SD.STYLE_ID 
WHERE  (U.UPC_TYPE = 1) AND (ST.ACTIVE_FLAG = 1) 

該查詢幾乎崩潰我們的服務器。我試圖通過將查詢分解爲更小的查詢來解決問題,但是我使用的臨時表變量導致tempdb數據庫填充硬盤驅動器。我認爲這是因爲服務器耗盡內存並崩潰。無論如何要解決這個問題嗎?

回答

1

正確的索引一定會幫助

IF

量排在此查詢沒有結束行的「不計其數」。

嘗試以下方法:

  • 加入上dbo.COLOR是如果存在的Fkey上dbo.STYLE_COLOR(COLOR_ID)=> dbo.COLOR(COLOR_ID)

正確指數過度(過度,應當審查)

USE MewLive 
CREATE INDEX ix1 ON dbo.STYLE_DETAIL (STYLE_ID) 
INCLUDE (STYLE_CODE, LONG_DESC) 
WHERE ACTIVE_FLAG = 1 
GO 
CREATE INDEX ix2 ON dbo.UPC (SKU_ID) 
INCLUDE(UPC_NUMBER) 
WHERE UPC_TYPE = 1 
GO 
CREATE INDEX ix3 ON dbo.SKU(STYLE_ID) 
INCLUDE(SKU_ID) 
GO 
CREATE INDEX ix3_alternative ON dbo.SKU(SKU_ID) 
INCLUDE(STYLE_ID) 
GO 
CREATE INDEX ix4 ON dbo.IB_INVENTORY_TOTAL(SKU_ID, LOCATION_ID) 
INCLUDE(TOTAL_ON_HAND_RETAIL) 
GO 
CREATE INDEX ix5 ON dbo.LOCATION(LOCATION_ID) 
INCLUDE(LOCATION_CODE) 
GO 
CREATE INDEX ix6 ON dbo.STYLE_COLOR(STYLE_ID) 
INCLUDE(SHORT_DESC,COLOR_ID) 
GO 
CREATE INDEX ix7 ON dbo.COLOR(COLOR_ID) 
GO 
CREATE INDEX ON dbo.STYLE_SIZE(STYLE_ID) 
INCLUDE(SIZE_MASTER_ID) 
GO 
CREATE INDEX ix8 ON dbo.SIZE_MASTER(SIZE_MASTER_ID) 
INCLUDE(PRIM_SIZE_LABEL) 
GO 
CREATE INDEX ix9 ON dbo.STYLE_VENDOR(STYLE_ID) 
INCLUDE(VENDOR_ID) 
GO 
CREATE INDEX ixA ON dbo.VENDOR(VENDOR_ID) 
INCLUDE(VENDOR_CODE) 
GO 
CREATE INDEX ON dbo.STYLE_DETAIL(STYLE_ID) 
INCLUDE(CURRENT_RETAIL) 

在SELECT列表取代U.UPC_TYPE,1 as UPC_TYPE,

+0

你可以有超過一列上的索引?某些列已經有主鍵或舊索引集。 – broke 2012-02-09 21:46:12

+0

@broke是的,它是允許的,這些索引可能比集羣更好地執行 – 2012-02-10 07:50:31

1

你可以隔離進口 - 通過SKU /位置/供應商/無論什麼和批量他們和運行多個查詢來獲取數據?是否有一個特殊的原因需要在一次碰撞中完成? (除了易於編寫查詢外)

+0

2個sql數據庫之間的表結構完全不同 – broke 2012-02-09 21:14:02

4

您是否嘗試過使用真正的表格而不是臨時表格。您可以使用SELECT INTO創建一個真實表來存儲結果,而不是臨時表。

語法是:

SELECT 
    U.UPC_NUMBER, 
    REPLACE(ST.STYLE_CODE, '.', ''). 
    .... 
INTO 
    MEWLIVE 
FROM 
    MewLive.dbo.STYLE AS ST INNER JOIN 
    ... 

該命令將創建表,並可能與您所看到的內存問題有所幫助。

此外,請嘗試查看查詢分析器中的執行計劃,或嘗試使用索引調整嚮導來建議可能有助於加快查詢速度的索引。

+0

好建議,我沒有考慮使用真正的表。至於索引調整嚮導,我在哪裏可以找到? – broke 2012-02-09 20:19:44

+0

-1表變量與臨時表非常相似。臨時表的唯一好處 - 您可以單獨創建索引並使用臨時表統計數據保護。 – 2012-02-09 20:51:51

+1

@OlegDok我認爲你曲解了。他建議使用真正的表格,而不是臨時表格或表格變量。如果tempdb是一個瓶頸(例如,在較慢的磁盤上,已經過載等),那麼在用戶數據庫中創建永久表(可能在更快的存儲上或者不太感到困難)可能會有好處。 – 2012-02-09 23:46:03

2

嘗試從Oracle服務器而不是從SQL服務器運行查詢。就目前而言,當查詢嘗試處理時,很可能會通過線路進行大量的通信。

通過預處理連接(也許有一個視圖),你只會發送結果。

關於過度規範化:您是否測試過速度是否存在問題?我發現很難相信,它可能是歸一化。

+0

您可以使用LinkedServer功能將SQL Server連接到Oracle服務器,然後如果使用OPENQUERY方法,則會在Oracle數據庫上處理查詢結果傳遞給SQL。 – Rikalous 2012-02-09 23:18:16