2009-09-25 74 views
0

我試圖加載從Oracle到SQL Server數據的性能(對不起,之前不寫這個)提高大型緩慢dataloading查詢

我有一個表(實際上是具有不同表中數據的視圖)與至少有100萬條記錄。我以這樣的方式設計我的包,使我具有業務邏輯的功能,並直接在選擇查詢中調用它們。

例:

X1(id varchar2) 
x2(id varchar2, d1 date) 
x3(id varchar2, d2 date) 

Select id, x, y, z, decode (.....), x1(id), x2(id), x3(id) 
FROM Table1 

注:我的表有20列,我呼籲ATLEAST 6-7列的5種不同的功能。 還有一些功能比較審計表中傳遞的參數和執行邏輯

我該怎樣才能提高查詢性能還是有更好的方法來做到這一點

我試圖做它在C#代碼,但最初選擇的記錄對於數據集來說足夠大,並且我會發現內存異常。

我的功能做選擇,然後例如進行邏輯:

Function(c_x2, eid) 

    Select col1 
    into p_x1 
    from tableP 
    where eid = eid; 

    IF (p_x1 = NULL) THEN 
    ret_var := 'INITIAL'; 
    ELSIF (p_x1 = 'L') AND (c_x2 = 'A') THEN 
    ret_var:= 'RL'; 

    INSERT INTO Audit 
     (old_val, new_val, audit_event, id, pname) 
    VALUES 
     (p_x1, c_x2, 'RL', eid, 'PackageProcName'); 

    ELSIF (p_x1 = 'A') AND (c_x2 = 'L') THEN 
    ret_var := 'GL'; 

    INSERT INTO Audit 
     (old_val, new_val, audit_event, id, pname) 
    VALUES 
     (p_x1, c_x2, 'GL', eid, 'PackgProcName'); 

    END IF; 

RETURN ret_var; 
+0

你會爲所有1,000,000條記錄運行這些函數嗎?是的,這需要一些時間來運行 - 當然不是毫秒。你的期望是什麼? – Guy 2009-09-25 14:02:09

+0

我從來沒有說我想要毫秒,它運行1小時..所以我想改善(提高)表現我說...我沒有寫我想讓它在一眨眼之間完成 – 2009-09-25 14:21:48

+1

看到我的最新回答編輯 – 2009-09-25 17:32:47

回答

0

首先,您需要找到性能問題的實際位置。然後你可以看看試圖解決它。

  1. 視圖的性能如何?在沒有任何函數調用的情況下執行 需要多長時間?嘗試運行命令

    它表現如何?這需要1分鐘還是1小時?

     
    create table the_view_table 
    as 
    select * 
    from the_view; 
    
  2. 函數的功能如何?根據描述,您正在進行大約500萬次函數調用。他們最好相當高效!功能也定義爲deterministic。如果使用關鍵字deterministic定義功能,則Oracle有機會優化掉某些呼叫。

  3. 有沒有減少函數調用次數的方法?一旦視圖被評估並且有數百行數據可用,函數將被調用。但都是來自查詢最高級別的輸入值?函數調用是否可以嵌入到較低級別的視圖中。考慮以下兩個查詢。哪個會更快?

    select 
        f.dim_id, 
        d.dim_col_1, 
        long_slow_function(d.dim_col_2) as dim_col_2 
    from large_fact_table f 
    join small_dim_table d on (f.dim_id = d.dim_id)
    select 
        f.dim_id, 
        d.dim_col_1, 
        d.dim_col_2 
    from large_fact_table f 
    join (
        select 
        dim_id, 
        dim_col_1, 
        long_slow_function(d.dim_col_2) as dim_col_2 
    from small_dim_table) d on (f.dim_id = d.dim_id)

    理想的情況下,它調用函數的次數更少第二個查詢應該可以跑得快一點。

性能問題可能是在這些地方,直到你調查這個問題,這將是很難知道從哪裏指導的調優工作。

+0

謝謝,我再次通過功能和查詢,並會看到我如何可以避免不必要的電話.. – 2009-09-25 15:47:18

0

創建你的桌子上的排序國際展覽中心。

Introduction to SQL Server Indizes,其他RDBMS是相似的。因爲你編輯你的問題

編輯:

使用視圖更是次優,從中查詢單行時尤其如此。我認爲你的「業務功能」實際上就像存儲過程一樣?

正如其他人所建議的,在SQL中總是要根據設置。我假定你已經這樣做了,因此我開始使用索引。

0

幾個祕訣:

  • 所有記錄不加載到RAM中,而是由一個處理這些之一。
  • 儘量在客戶端上運行儘可能多的功能。數據庫執行用戶定義函數的速度非常慢。
  • 如果您需要連接兩個表,有時可能會在客戶端上創建兩個連接。通過連接1獲取數據主數據,使用連接2獲取審計數據。以相同的方式爲兩個連接排序數據,以便您可以從兩個連接中讀取單個記錄並執行您所需的任何操作。
  • 如果您的函數始終爲相同的輸入返回相同的結果,請使用計算列或實例化視圖。數據庫將運行一次函數並將其保存在某個表中。那會讓INSERT變慢,但是SELECT很快。
+0

我寫了相同的代碼在c#中使用datareader我得到每一行,並在C#中執行邏輯,然後插入...這也需要很多時間... 我使用的函數帶參數和執行一些邏輯:如比較,然後計算日期或其他數據... 我沒有在我的查詢中使用任何連接 – 2009-09-25 13:40:24

+3

(-1)使用基於集合的SQL - 不按記錄記錄。嘗試使用快速的原生SQL函數。使用數據庫作爲數據庫 - 它是爲連接/更新/查詢而構建的。不要以爲你可以用我們的編程技巧重新編寫數據庫。 – Guy 2009-09-25 14:00:22

+0

我正在做C#中的功能不是在SQL中,如果我嘗試加載一切在我的記憶中一次,它是thorwing outof內存異常,這就是爲什麼我使用datareader ...我知道什麼數據庫建... ...我試圖得到答案,並學習不重寫數據庫plz ... – 2009-09-25 14:20:23

4

我得到的每一行和C#進行 邏輯,然後插入

如果從SELECT可能INSERT:

INSERT INTO YourNewTable 
     (col1, col2, col3) 
    SELECT 
     col1, col2, col3 
     FROM YourOldTable 
     WHERE .... 

這將運行顯著快而不是單個查詢,然後循環遍歷結果集並對每行都進行INSERT。

編輯作爲OP問題編輯:

你應該能夠取代函數調用普通的SQL查詢中。使用LEFT JOIN表P模擬「初始」,可以使用CASE計算「RL」或「GL」。基於OP最近的評論

編輯

,因爲您從Oracle數據加載到SQL Server中,這是我會做什麼:大多數人,可以幫助已經轉移上,而不會再次讀取這個問題,所以在你說:1)你需要將數據從Oracle(版本)加載到SQL Server版本2)中打開一個新問題,目前你正在從一個查詢處理C#中的每一行並將其插入到SQL Server中,是慢的。和所有其他細節。將數據批量加載到SQL Server有很多更好的方法。至於這個問題,你可以接受一個答案,在你解釋你需要提出一個新問題時回答自己,或者讓它不被接受。

+0

插入選擇將無法爲我工作,因爲我正在加載oracle表到sql服務器 而我不能做插入審計,如果我使用CASE – 2009-09-25 15:26:58

+1

哇!不會_i'm加載到sql server_的oracle表已經是你在問題中的東西?靠近頂部? – 2009-09-25 15:37:33

2

我的建議是你做而不是使用函數,然後在其他SELECT語句中調用它們。這:

SELECT t.id, ... 
     x1(t.id) ... 
    FROM TABLE t 

...相當於:

SELECT t.id, ... 
     (SELECT x.column FROM x1 x WHERE x.id = t.id) 
    FROM TABLE t 

封裝不SQL工作中使用C#/等時等。雖然該方法使維護更容易,但性能會受到影響,因爲子選擇將針對每個返回的行執行。

一個更好的方法,是更新的支撐功能,包括連接標準(IE:「where x.id = t.id」爲缺乏真正的一)在SELECT:

SELECT x.id 
     x.column 
    FROM x1 x 

...所以你可以使用它作爲JOIN:

SELECT t.id, ... 
     x1.column 
    FROM TABLE t 
    JOIN (SELECT x.id, 
       x.column 
      FROM MY_PACKAGE.x) x1 ON x1.id = t.id 

我更喜歡具有摻入功能邏輯進入查詢進行維護的緣故,但有時不能得到幫助。

+0

+1,在這裏工作有多個問題,我想到了這一點,但只是從SELECT中插入INSERT。你解釋的功能問題比我更好... – 2009-09-25 14:15:06

+0

有人可以編輯以上評論我..我想添加代碼段 – 2009-09-25 14:29:50

+0

編輯你的問題,並把代碼放在那裏,據我可以告訴你只能__BOLD__和_ITALICS_中的評論,沒有代碼格式 – 2009-09-25 14:34:57

1

就我個人而言,我會創建一個SSIS導入來完成這項任務。使用abulk插入您可以極大地提高速度,SSIS可以在批量插入後處理函數部分。