2009-06-26 63 views
2

我目前在正在使用的數據庫的基於OFBiz的ERP 的部署工作是Oracle 10g企業如何使用SELECT DISTINCT

其中最大的問題是一些Oracle的性能問題,分析提高Oracle的性能ofbiz日誌,以下查詢:

SELECT DISTINCT ORDER_ID, ORDER_TYPE_ID, ORDER_NAME, EXTERNAL_ID, 
SALES_CHANNEL_ENUM_ID, ORDER_DATE, ENTRY_DATE, VISIT_ID, STATUS_ID, CREATED_BY, 
FIRST_ATTEMPT_ORDER_ID, CURRENCY_UOM, SYNC_STATUS_ID, BILLING_ACCOUNT_ID, 
ORIGIN_FACILITY_ID, WEB_SITE_ID, PRODUCT_STORE_ID, TERMINAL_ID, TRANSACTION_ID, 
AUTO_ORDER_SHOPPING_LIST_ID, NEEDS_INVENTORY_ISSUANCE, IS_RUSH_ORDER, INTERNAL_CODE, 
REMAINING_SUB_TOTAL, GRAND_TOTAL, LAST_UPDATED_STAMP, LAST_UPDATED_TX_STAMP, CREATED_STAMP, 
CREATED_TX_STAMP, RECIBIR_BODEGAL, RECEPCIONADA_BODEGAL, FECHA_RECEPCION_BODEGAL FROM 
ERP.ORDER_HEADER WHERE ((STATUS_ID = :v0 OR STATUS_ID = :v1 OR STATUS_ID = :v2) AND 
(ORDER_TYPE_ID = :v3)) ORDER BY ORDER_DATE DESC 

是非常緩慢的。我們已經測試了執行沒有DISTINCT的查詢,大約需要30秒。表中有4000,000多個寄存器。 有指數PK場的orderId和幾乎所有其他領域

與DISTINCT解釋計劃是:

SELECT STATEMENT() (null) 
SORT (ORDER BY) (null) 
    HASH (UNIQUE) (null) 
    TABLE ACCESS (FULL) ORDER_HEADER 

並沒有DISTINCT是:

SELECT STATEMENT() (null) 
SORT (ORDER BY) (null) 
    TABLE ACCESS (FULL) ORDER_HEADER 

關於調整Oracle任何想法提高這種查詢的性能? 這是非常困難的重寫查詢,因爲被ofbiz的 自動生成的,所以我認爲解決的辦法是關於調整Oracle提前

感謝

編輯:我分析了使用TKPROF查詢,由羅布麪包車Wijk的建議和haffax,結果就是下面的

******************************************************************************** 

SELECT DISTINCT ORDER_ID, ORDER_TYPE_ID, ORDER_NAME, EXTERNAL_ID, 
SALES_CHANNEL_ENUM_ID, ORDER_DATE, ENTRY_DATE, VISIT_ID, STATUS_ID, CREATED_BY, 
FIRST_ATTEMPT_ORDER_ID, CURRENCY_UOM, SYNC_STATUS_ID, BILLING_ACCOUNT_ID, 
ORIGIN_FACILITY_ID, WEB_SITE_ID, PRODUCT_STORE_ID, TERMINAL_ID, TRANSACTION_ID, 
AUTO_ORDER_SHOPPING_LIST_ID, NEEDS_INVENTORY_ISSUANCE, IS_RUSH_ORDER, INTERNAL_CODE, 
REMAINING_SUB_TOTAL, GRAND_TOTAL, LAST_UPDATED_STAMP, LAST_UPDATED_TX_STAMP, CREATED_STAMP, 
CREATED_TX_STAMP, RECIBIR_BODEGAL, RECEPCIONADA_BODEGAL, FECHA_RECEPCION_BODEGAL FROM 
ERP.ORDER_HEADER WHERE STATUS_ID = 'ORDER_COMPLETED' ORDER BY ORDER_DATE DESC 

call  count  cpu elapsed  disk  query current  rows 
------- ------ -------- ---------- ---------- ---------- ---------- ---------- 
Parse  1  0.03  0.01   0   0   0   0 
Execute  1  0.00  0.00   0   0   0   0 
Fetch  1  9.10  160.81  66729  65203   37   50 
------- ------ -------- ---------- ---------- ---------- ---------- ---------- 
total  3  9.14  160.83  66729  65203   37   50 

Misses in library cache during parse: 1 
Optimizer mode: ALL_ROWS 
Parsing user id: 58 

Elapsed times include waiting on following events: 
    Event waited on        Times Max. Wait Total Waited 
    ---------------------------------------- Waited ---------- ------------ 
    SQL*Net message to client      1  0.00   0.00 
    db file scattered read      8178  0.28  146.55 
    direct path write temp      2200  0.04   4.22 
    direct path read temp       36  0.14   2.01 
    SQL*Net more data to client      3  0.00   0.00 
    SQL*Net message from client      1  3.36   3.36 
******************************************************************************** 

如此看來問題出在「DB文件分散讀」,任何想法如何優化Oracle爲了減少此事件中的等待?

跟進新TKPROF結果,此時關閉會話:

******************************************************************************** 

SELECT DISTINCT ORDER_ID, ORDER_TYPE_ID, ORDER_NAME, EXTERNAL_ID, 
SALES_CHANNEL_ENUM_ID, ORDER_DATE, ENTRY_DATE, VISIT_ID, STATUS_ID, CREATED_BY, 
FIRST_ATTEMPT_ORDER_ID, CURRENCY_UOM, SYNC_STATUS_ID, BILLING_ACCOUNT_ID, 
ORIGIN_FACILITY_ID, WEB_SITE_ID, PRODUCT_STORE_ID, TERMINAL_ID, TRANSACTION_ID, 
AUTO_ORDER_SHOPPING_LIST_ID, NEEDS_INVENTORY_ISSUANCE, IS_RUSH_ORDER, INTERNAL_CODE, 
REMAINING_SUB_TOTAL, GRAND_TOTAL, LAST_UPDATED_STAMP, LAST_UPDATED_TX_STAMP, CREATED_STAMP, 
CREATED_TX_STAMP, RECIBIR_BODEGAL, RECEPCIONADA_BODEGAL, FECHA_RECEPCION_BODEGAL FROM 
ERP.ORDER_HEADER WHERE STATUS_ID = 'ORDER_COMPLETED' ORDER BY ORDER_DATE DESC 

call  count  cpu elapsed  disk  query current  rows 
------- ------ -------- ---------- ---------- ---------- ---------- ---------- 
Parse  1  0.03  0.01   0   0   0   0 
Execute  2  0.00  0.00   0   0   0   0 
Fetch  1  8.23  47.66  66576  65203   31   50 
------- ------ -------- ---------- ---------- ---------- ---------- ---------- 
total  4  8.26  47.68  66576  65203   31   50 

Misses in library cache during parse: 1 
Optimizer mode: ALL_ROWS 
Parsing user id: 58 

Rows  Row Source Operation 
------- --------------------------------------------------- 
    50 SORT ORDER BY (cr=65203 pr=66576 pw=75025 time=47666679 us) 
3456659 TABLE ACCESS FULL ORDER_HEADER (cr=65203 pr=65188 pw=0 time=20757300 us) 


Elapsed times include waiting on following events: 
    Event waited on        Times Max. Wait Total Waited 
    ---------------------------------------- Waited ---------- ------------ 
    SQL*Net message to client      1  0.00   0.00 
    db file scattered read      8179  0.14   34.96 
    direct path write temp      2230  0.00   3.91 
    direct path read temp       52  0.14   0.84 
    SQL*Net more data to client      3  0.00   0.00 
    SQL*Net message from client      1  1510.62  1510.62 
******************************************************************************** 
+0

列order_date的,order_type_id和STATUS_ID其中空。將它們設置爲NOT NULL之後,查詢將在約50秒內執行。現在,具有獨特性的計劃等同於沒有獨特性的計劃。最慢的部分是SORT – Ismael 2009-06-27 19:50:50

回答

1

如果兩個查詢之間的差異很大,那將是令人驚訝的。您提到沒有DISTINCT的查詢大約需要30秒。使用DISTINCT的查詢需要多少時間?

當你用「alter session set events'10046跟蹤名稱上下文永遠,級別8'」跟蹤會話並在查詢完成後斷開連接之後,可以使用DISTINCT顯示查詢的tkprof輸出嗎?通過這種方式,我們可以看到實際花費的時間以及是否在等待某些內容(「直接路徑讀取溫度」可能?)

Regards, Rob。


跟進,後TKPROF文件發佈:

我看你設法讓TKPROF輸出,可惜你沒有創建TKPROF文件之前斷開的會話。現在,光標處於打開狀態,並且無法將STAT#行寫入跟蹤文件。這就是爲什麼您的tkprof文件中沒有計劃/行源操作的原因。如果你能重複這個過程,如果下面的建議變成垃圾,那將是很好的。

從我身邊一點點炒作:我認爲DISTINCT幾乎無操作,因爲你選擇這麼多列。如果這是真的,那麼你的謂詞「WHERE STATUS_ID ='ORDER_COMPLETED'」是非常有選擇性的,你將從這個列有一個索引中受益。創建索引後,請確保正確分析索引,如果數據值偏斜,則甚至可以使用直方圖進行分析。最終的結果將是這個查詢的一個不同的計劃,從一個INDEX RANGE SCAN開始,然後是一個TABLE ACCESS BY ROWID,導致一個非常快的查詢。

您已經創建了索引之後,你可以有表重新分析,包括使用此語句直方圖:

EXEC dbms_stats.gather_table_stats([所有人],[TABLE_NAME],級聯=>真,了method_opt = > 'FOR ALL索引列SIZE')

問候, 羅布。

2

既然你根據order_date重要的是,你必須在該字段降序索引排序結果。 同時告訴oracle你希望使用這個索引。首位order_date現場查詢和使用提示像

SELECT /*+ index(HEADERS IDX_ORDER_DATE_DESC) */ ... 
FROM ERP.ORDER_HEADER HEADERS 
WHERE ... 
ORDER BY ORDER_DATE DESC 

這與其說是關於有指標,而是關於告訴Oracle使用它們。 Oracle對指數非常挑剔。根據最重要的查詢選擇索引時,您會獲得最佳結果。如有疑問,請撥打trace a query。通過這種方式,您可以看到查詢oracle的哪一部分花費最多時間以及您的索引是否實際被拾取。跟蹤性能問題時,跟蹤功能非常重要。

+2

在這種簡單的情況下建議索引提示,而不是讓基於成本的優化器發揮作用,這不是我最喜歡的建議。然後,一個簡單的評論「Oracle對索引非常挑剔」是將鼠標移向downvote按鈕。我只會留下這句話,因爲關於追蹤的最後三句話是非常明智的:-) – 2009-06-27 22:44:38

1

使用PRIMARY KEY約束將ORDER_ID聲明爲PK嗎?因爲如果是這樣的話,我希望優化器能夠認識到DISTINCT在這個查詢中是多餘的,並優化它。如果沒有這種限制,它不會知道這是多餘的,因此會花費不必要的和相當大的努力來「清除」結果。

-1

Oracle在每次運行查詢(TABLE ACCESS(FULL))時訪問整個表。 創建的STATUS_ID和ORDER_TYPE_ID列

CREATE INDEX ERP.ORDER_HEADER_I1 ON ERP.ORDER_HEADER (STATUS_ID, ORDER_TYPE_ID); 

的指數將有很大的幫助,尤其是如果有在ORDER_HEADER表STATUS_ID和ORDER_TYPE_ID的幾個不同的值。

0

當故障排除後,我沒有SQL我發現DBMS_SQLTUNE封裝節省了大量的時間的控制應用。見http://download.oracle.com/docs/cd/B28359_01/appdev.111/b28419/d_sqltun.htm,是的,不幸的是,你應該被授權使用它。

有此包到運行鍼對在共享池中或AWR儲存庫中的特定SQL_ID調諧分析程序。如果對附加索引有任何改進,分析將包含索引建議。更重要的是,分析器可能會發現一個改進的訪問路徑,它可以通過Oracle調用SQL Profile來實現 - 這是一組將在執行sql_id時存儲和使用的提示。發生這種情況時,不需要在SQL語句中編寫提示,如果應用程序在語句中生成文字值而不是綁定變量,也可以選擇執行模糊匹配。

當然這個工具不應該是理解應用程序的替代品,它的數據結構,但通過詳細介紹一個更好的計劃(如果找到)的執行路徑輸出讀書可以教育。