簡體   English   中英

增強大型慢速數據加載查詢的性能

[英]Enhance performance of large slow dataloading query

我正在嘗試將數據從oracle加載到sql server(很抱歉,以前沒有寫過此信息)

我有一個表(實際上是一個視圖,其中包含來自不同表的數據)至少具有一百萬條記錄。 我以一種具有業務邏輯功能的方式設計了程序包,並直接在select查詢中調用它們。

例如:

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列,我至少要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;

我正在獲取每一行並在C#中執行邏輯,然后插入

如果可能,請從SELECT中插入:

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

這將運行多單查詢顯著更快哪里,那么你在結果集循環,並為每個行的一個INSERT。

編輯作為OP問題編輯:

您應該能夠在查詢中替換對普通SQL的函數調用。 使用LEFT JOIN tableP模仿“ initial”,並且可以使用CASE計算“ RL”或“ GL”。

根據OP最近的評論進行編輯

由於您是將數據從Oracle加載到SQL Server中,所以我會這樣做:大多數可以幫助您的人已經繼續前進,不會再閱讀此問題,因此在您說一個新問題的地方打開一個新問題:1)您需要加載數據(從Oracle(版本)到SQL Server版本2)當前,您正在通過一個查詢來加載它,並處理C#中的每一行並將其插入SQL Server,這很慢。 以及所有其他詳細信息。 有很多更好的方法將數據批量加載到SQL Server。 對於這個問題,您可以接受答案,在解釋您需要提出新問題的地方回答自己,或者不接受。

我的建議是不要使用函數,然后在其他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

像在使用C#/ etc一樣,封裝在SQL中不起作用。 盡管該方法使維護更加容易,但是由於子選擇將針對返回的每一行執行,因此性能會受到影響。

更好的方法是將支持功能更新為在SELECT中包括where x.id = t.id條件(即:缺少真實值的“ where x.id = t.id ”):

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

我更喜歡為了維護而不得不將函數邏輯合並到查詢中,但是有時它無濟於事。

我個人將創建一個SSIS導入來執行此任務。 使用大容量插件可以顯着提高速度,而SSIS可以在批量插入后處理功能部件。

在表上創建一個排序的intex。

SQL Server Indizes簡介 ,其他RDBMS相似。

編輯,因為您編輯了問題:

使用視圖更為不理想,尤其是在從視圖查詢單行時。 我認為您的“業務功能”實際上類似於存儲過程嗎?

就像其他人建議的那樣,在SQL中總是基於集合。 我以為您已經做到了,因此開始使用索引的提示。

一些提示:

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

首先,您需要找到實際的性能問題所在。 然后,您可以查看嘗試解決它的方法。

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

    它的表現如何? 需要1分鍾還是1小時?

    \n 創建表the_view_table\n \n 選擇 *\n 從the_view;\n
  2. 功能執行得如何? 根據描述,您將進行大約500萬個函數調用。 他們最好效率很高! 也定義為deterministic的功能。 如果使用deterministic關鍵字定義函數,則Oracle有機會優化一些調用。

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

      選擇 \n   f.dim_id, \n   d.dim_col_1, \n   long_slow_function(d.dim_col_2)as dim_col_2\n 來自large_fact_table f\n 加入small_dim_table d on(f.dim_id = d.dim_id) 
      選擇 \n   f.dim_id, \n   d.dim_col_1, \n   d.dim_col_2\n 來自large_fact_table f\n 加入(\n   選擇 \n     dim_id, \n     dim_col_1, \n     long_slow_function(d.dim_col_2)as dim_col_2\n 來自small_dim_table)d on(f.dim_id = d.dim_id) 

    理想情況下,第二個查詢應運行得更快,因為它調用函數的次數更少。

性能問題可能出在任何這些地方,並且在您調查問題之前,很難知道將調整工作定向到何處。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM