2008-12-10 60 views
2

我正在移植一個創建兩個表的MASSIVE CROSS JOIN的進程。生成的表格包含15m個記錄(看起來像進程使用2600行表格和12000行表格進行30米交叉連接,然後進行一些分組,將其分成兩半)。行相對較窄 - 只有6列。它已經運行了5個小時,沒有完成的跡象。我只注意到已知的好東西和我期望的交叉連接之間的計數差異,所以我的輸出沒有將最終表格減半的分組或重複數 - 但這看起來好像不會完成任何操作時間很快。SQL Server 2005中的大規模CROSS JOIN

首先,我將着眼於從這個過程中刪除這個表,如果可能的話 - 顯然它可以通過單獨連接到兩個表來取代,但是現在我無法查看它在其他地方的使用情況。

但是,考慮到現有的流程(在較少的時間內,在功能較弱的機器上,使用FOCUS語言),是否有任何選項用於改進SQL Server(2005)中的大型文件系統的性能(硬件是不是一個真正的選擇,這個盒子是一個32位的32位RAM的64位8路)?

詳情:

這是寫在FOCUS這樣(我試圖產生相同的輸出,這是一個跨在SQL JOIN):

JOIN CLEAR * 
DEFINE FILE COSTCENT 
    WBLANK/A1 = ' '; 
    END 
TABLE FILE COSTCENT 
    BY WBLANK BY CC_COSTCENT 
    ON TABLE HOLD AS TEMPCC FORMAT FOCUS 
    END 

DEFINE FILE JOINGLAC 
    WBLANK/A1 = ' '; 
    END 
TABLE FILE JOINGLAC 
    BY WBLANK BY ACCOUNT_NO BY LI_LNTM 
    ON TABLE HOLD AS TEMPAC FORMAT FOCUS INDEX WBLANK 

JOIN CLEAR * 
JOIN WBLANK IN TEMPCC TO ALL WBLANK IN TEMPAC 
DEFINE FILE TEMPCC 
    CA_JCCAC/A16=EDIT(CC_COSTCENT)|EDIT(ACCOUNT_NO); 
    END 
TABLE FILE TEMPCC 
    BY CA_JCCAC BY CC_COSTCENT AS COST CENTER BY ACCOUNT_NO 
    BY LI_LNTM 
    ON TABLE HOLD AS TEMPCCAC 
    END 

因此所需的輸出確實是一個CROSS JOIN(它將連接來自每邊的空白列)。

在SQL:

CREATE TABLE [COSTCENT](
     [COST_CTR_NUM] [int] NOT NULL, 
     [CC_CNM] [varchar](40) NULL, 
     [CC_DEPT] [varchar](7) NULL, 
     [CC_ALSRC] [varchar](6) NULL, 
     [CC_HIER_CODE] [varchar](20) NULL, 
CONSTRAINT [PK_LOOKUP_GL_COST_CTR] PRIMARY KEY NONCLUSTERED 
(
     [ID] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY 
= OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 

CREATE TABLE [JOINGLAC](
     [ACCOUNT_NO] [int] NULL, 
     [LI_LNTM] [int] NULL, 
     [PR_PRODUCT] [varchar](5) NULL, 
     [PR_GROUP] [varchar](1) NULL, 
     [AC_NAME_LONG] [varchar](40) NULL, 
     [LI_NM_LONG] [varchar](30) NULL, 
     [LI_INC] [int] NULL, 
     [LI_MULT] [int] NULL, 
     [LI_ANLZ] [int] NULL, 
     [LI_TYPE] [varchar](2) NULL, 
     [PR_SORT] [varchar](2) NULL, 
     [PR_NM] [varchar](26) NULL, 
     [PZ_SORT] [varchar](2) NULL, 
     [PZNAME] [varchar](26) NULL, 
     [WANLZ] [varchar](3) NULL, 
     [OPMLNTM] [int] NULL, 
     [PS_GROUP] [varchar](5) NULL, 
     [PS_SORT] [varchar](2) NULL, 
     [PS_NAME] [varchar](26) NULL, 
     [PT_GROUP] [varchar](5) NULL, 
     [PT_SORT] [varchar](2) NULL, 
     [PT_NAME] [varchar](26) NULL 
) ON [PRIMARY] 

CREATE TABLE [JOINCCAC](
     [CA_JCCAC] [varchar](16) NOT NULL, 
     [CA_COSTCENT] [int] NOT NULL, 
     [CA_GLACCOUNT] [int] NOT NULL, 
     [CA_LNTM] [int] NOT NULL, 
     [CA_UNIT] [varchar](6) NOT NULL, 
CONSTRAINT [PK_JOINCCAC_KNOWN_GOOD] PRIMARY KEY CLUSTERED 
(
     [CA_JCCAC] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY 
= OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 

隨着SQL代碼:

INSERT INTO [JOINCCAC] 
     (
     [CA_JCCAC] 
     ,[CA_COSTCENT] 
     ,[CA_GLACCOUNT] 
     ,[CA_LNTM] 
     ,[CA_UNIT] 
     ) 
     SELECT Util.PADLEFT(CONVERT(varchar, CC.COST_CTR_NUM), '0', 
            7) 
       + Util.PADLEFT(CONVERT(varchar, GL.ACCOUNT_NO), '0', 
             9) AS CC_JCCAC 
       ,CC.COST_CTR_NUM AS CA_COSTCENT 
       ,GL.ACCOUNT_NO % 900000000 AS CA_GLACCOUNT 
       ,GL.LI_LNTM AS CA_LNTM 
       ,udf_BUPDEF(GL.ACCOUNT_NO, CC.COST_CTR_NUM, GL.LI_LNTM, 'N') AS CA_UNIT 
     FROM JOINGLAC AS GL 
     CROSS JOIN COSTCENT AS CC 

根據如何該表隨後被使用,它應該能夠從工藝被淘汰,通過簡單地加入到這兩個原始表格都是用來構建它的。然而,這是一個非常大的移植工作,我可能在一段時間內找不到該表的使用情況,所以我想知道是否有任何技巧及時地處理這樣的大表(特別是考慮到現有的FOCUS過程能夠更迅速地完成)。這樣我就可以驗證替換查詢的構建的正確性,然後再用視圖或其他方法來分解它。

我也在考慮分解UDF和字符串操作,並首先執行CROSS JOIN來打破這個過程。

效果爲止:

事實證明,該UDF的貢獻做了很多(負面的)的性能。但是,在15米排交叉和30米排交叉之間似乎也有很大差異。我沒有SHOWPLAN權限(boo hoo),所以我不知道改變索引後它使用的計劃是好還是壞。我還沒有重構它,但我期待整個桌子很快就會消失。

+1

「MASSIVE CROSS JOIN」該語法應該引入到SQL語言中。 :) – 2008-12-10 05:52:07

回答

2

檢查該查詢只顯示一個表中使用的一列,而另一個表中只使用兩列。由於列使用的非常低的數字,這種查詢可以很容易地與覆蓋索引增強:

CREATE INDEX COSTCENTCoverCross ON COSTCENT(COST_CTR_NUM) 
CREATE INDEX JOINGLACCoverCross ON JOINGLAC(ACCOUNT_NO, LI_LNTM) 

這裏是我的問題,爲進一步優化:

當你把在查詢分析器查詢和猛擊「顯示估計執行計劃」按鈕,它將顯示它將要執行的操作的圖形表示。

連接類型:應該有一個嵌套的循環連接。 (其他選項是合併連接和散列連接)。如果你看到嵌套循環,那麼確定。如果您看到合併連接或散列連接,請告訴我們。

表格訪問順序:一直到頂部並一直滾動到右側。第一步應該是訪問一個表格。哪個表是哪個表以及使用哪種方法(索引掃描,聚簇索引掃描)?用什麼方法訪問另一個表?並行性:您應該在計劃中的幾乎所有圖標上看到小鋸齒箭頭,表示正在使用並行操作。如果你沒有看到這個,就有一個主要問題!

udf_BUPDEF關注我。它是否從附加表中讀取? Util.PADLEFT更少關注我,但仍然......它是什麼?如果它不是數據庫對象,那麼可以考慮使用它來代替:

RIGHT('z00000000000000000000000000' + columnName, 7) 

JOINCCAC上是否存在任何觸發器?如何索引?使用這麼大的插入,您需要刪除該表上的所有觸發器和索引。

1

分解查詢使其成爲簡單的交叉連接。

 

    SELECT CC.COST_CTR_NUM, GL.ACCOUNT_NO 
       ,CC.COST_CTR_NUM AS CA_COSTCENT 
       ,GL.ACCOUNT_NO AS CA_GLACCOUNT 
       ,GL.LI_LNTM AS CA_LNTM 
-- I don't know what is BUPDEF doing? but remove it from the query for time being 
--    ,udf_BUPDEF(GL.ACCOUNT_NO, CC.COST_CTR_NUM, GL.LI_LNTM, 'N') AS CA_UNIT 
     FROM JOINGLAC AS GL 
     CROSS JOIN COSTCENT AS CC 
 

看看簡單的交叉連接有多好?(沒有應用任何功能)

+0

如果這工作得很快,請嘗試只做SELECT(使用所應用的功能)並查看,如果仍然可以? – shahkalpesh 2008-12-10 05:11:00

+0

已發佈搜索結果 – 2008-12-17 15:06:29

+0

UDF性能(它們是標量並且不訪問表)是關鍵並且非常可怕 - 兩個UDF每秒只能處理大約300行。我目前正在尋找解決方法。 – 2009-02-26 18:52:06

2

繼續別人的說法,包含在select中使用查詢的數據庫函數總是使我的查詢非常緩慢。關閉我的頭頂,我相信我有一個查詢在45秒內運行,然後我刪除了該功能,然後結果是0秒:)

因此檢查udf_BUPDEF沒有做任何查詢。