Frage

Ich bin zurzeit in der Bereitstellung einer OFBiz basierte ERP Die verwendete Datenbank ist Oracle 10g Enterprise

Eines der größten Probleme ist, einige oracle-performance-Problemen, die Analyse der ofbiz Protokolle, die folgende Abfrage:

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

ist sehr langsam.Wir haben getestet das ausführen der Abfrage ohne das DISTINCT und es dauert etwa 30 Sekunden.Es gibt 4.000.000+ registriert in der Tabelle.Es gibt index für das PK-Feld orderId und fast jedes andere Feld

Die EXPLAIN-PLAN mit klaren ist:

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

und ohne das DISTINCT ist:

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

irgendwelche Ideen, tuning-oracle zur Verbesserung der Leistung dieser Art von Abfragen?Es ist sehr schwierig, die Abfrage neu schreiben, weil automatisch durch ofbiz also, ich denke, die Lösung ist über tuning oracle

vielen Dank im Voraus

EDIT:Ich Analysierte die Abfrage mit tkprof ,wie vorgeschlagen, von Rob van Wijk und haffax,und das Ergebnis ist die folgende

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

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
********************************************************************************

So scheint es, das problem ist das 'db file scattered read', beliebige Ideen auf how to tune oracle in Auftrag zu reduzieren die Wartezeit in diesem Fall?

Follow-up mit die neue tkprof Ergebnis, dieses mal schließen der Sitzung:

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

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
********************************************************************************
War es hilfreich?

Lösung

Wenn die Differenz zwischen den beiden Abfragen erheblich ist, das wäre überraschend. Sie erwähnen, dass die Abfrage ohne DISTINCT etwa 30 Sekunden dauert. Wie viel Zeit die Abfrage mit dem DISTINCT nehmen?

Können zeigen Sie die tkprof Ausgabe der Abfrage mit dem DISTINCT, nachdem Sie die Sitzung mit einem „Session Set Ereignissen‚10046 Spur Namenskontext für immer, Ebene 8‘ändern“ verfolgt, und trennt, nachdem die Abfrage beendet hat? Auf diese Weise können wir sehen, wo die Zeit tatsächlich ausgegeben wird und an wen sie auf etwas warten (vielleicht „direkten Weg lesen temp“?)

Viele Grüße, Rob.


Followup, nachdem die tkprof Datei wurde geschrieben:

Ich sehe, Sie es geschafft, die tkprof Ausgabe zu erhalten, aber leider haben Sie nicht trennen die Sitzung vor der tkprof Datei. Nun wurde der Cursor nach links offen und es ist fehlgeschlagen STAT # Zeilen in der Trace-Datei zu schreiben. Aus diesem Grund Sie nicht über einen Plan / row Quellbetrieb in Ihrer tkprof-Datei haben. Es wäre schön, wenn Sie den Vorgang wiederholen kann, wenn der Vorschlag Müll sein unten herausstellt.

Eine wenig Spekulation von meiner Seite: Ich denke, die DISTINCT ist fast ein no-op, weil Sie so viele Spalten auswählen. Wenn dies wahr ist, dann ist Ihr Prädikat „WHERE status_id =‚ORDER_COMPLETED‘“ ist sehr selektiv, und Sie werden einen Index aus, die auf dieser Spalte profitieren. Nachdem Sie den Index zu erstellen, stellen Sie sicher, dass Sie es richtig analysieren, vielleicht sogar mit einem Histogramm auf, wenn Datenwerte verzerrt sind. Das Endergebnis wird ein anderer Plan für diese Abfrage sein, mit einem INDEX RANGE SCAN starten, durch eine TABLE ACCESS BY ROWID gefolgt, zu einer sehr schnellen Abfrage führt.

Nachdem Sie einen Index erstellt haben, können Sie die Tabelle erneut analysiert, einschließlich Histogramme diese Anweisung:

exec dbms_stats.gather_table_stats ([owner], [table_name], Kaskade => true, method_opt => 'FÜR ALLE indizierte Spalten SIZE')

Viele Grüße, Rob.

Andere Tipps

Da sind Sie die Bestellung Ergebnisse nach order_date es ist wichtig, dass Sie ein absteigender index auf das Feld.Auch sagen, oracle, dass Sie möchten, verwenden Sie diesen index.Legen Sie die order_date Feld zunächst in der Abfrage, und verwenden Sie einen Hinweis, wie

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

Es ist nicht so viel darüber, dass die Indizes, sondern darüber erzählen, oracle, Sie zu benutzen.Oracle ist sehr wählerisch über die Indizes.Sie erhalten die besten Ergebnisse, wenn Sie wählen Indizes nach Ihren wichtigsten Abfragen.Wenn Sie Zweifel haben, trace eine Abfrage.Auf diese Weise können Sie sehen, in welchem Teil der Abfrage oracle verbringt die meiste Zeit und ob Ihre Indizes sind tatsächlich abgeholt wird oder nicht.Tracing ist von unschätzbarem Wert bei der Bekämpfung von performance-Problemen.

Ist erklärt ORDER_ID als PK eine PRIMARY KEY-Einschränkung verwenden? Denn wenn es ist, würde ich die optimiser erwarten zu erkennen, dass die DISTINCT in dieser Abfrage überflüssig ist und optimieren Sie es heraus. Ohne die Einschränkung, wird es nicht wissen, dass es überflüssig ist, und wird so unnötig und erhebliche Anstrengungen in „de-duping“ die Ergebnisse aufwenden.

Versuche Hash-Aggregation zu deaktivieren:

select /*+ no_use_hash_aggregation*/ distinct ...

http://oracle-randolf.blogspot.com/2011/ 01 / Hash-aggregation.html

Wenn Anwendungen zur Fehlerbehebung, wo ich habe keine Kontrolle über die SQL Ich finde, dass das Paket dbms_sqltune viel Zeit spart. Siehe http://download.oracle.com/docs /cd/B28359_01/appdev.111/b28419/d_sqltun.htm , und ja, leider sollten Sie lizenziert werden, es zu benutzen.

Es gibt Verfahren in diesem Paket eine Tuning-Analyse gegen einen bestimmten sql_id im gemeinsamen Pool oder das AWR-Repository laufen. Die Analyse wird die Indizierung Empfehlungen enthalten, wenn es irgendwelche Verbesserungen mit zusätzlichen Indizes vorgenommen werden. Noch wichtiger ist, kann der Analysator einen verbesserten Zugriffspfad entdecken, die es mit dem, was Oracle ruft ein SQL Profil implementieren kann - das ist eine Reihe von Hinweisen, die diese sql_id gespeichert und verwendet werden, wann immer ausgeführt wird. Dies geschieht, ohne die Hinweise zu erfordern in der SQL-Anweisung kodiert werden, und es gibt auch eine Option, zu tun, was Sie als Fuzzy Matching denken können, wenn Ihre Anwendung Literalwerte in der Anweisung erzeugt anstelle von Bind-Variablen.

Natürlich sollte dieses Tool kein Ersatz sein für die Anwendung zu verstehen, und es ist Datenstrukturen, sondern durch die Ausgabe zu lesen, die den Ausführungspfad eines besseren Plan Details (falls gefunden) kann lehrreich sein.

Oracle Zugriff auf die gesamte Tabelle jedes Mal, wenn Sie die Abfrage (TABLE ACCESS (FULL)) durchgeführt. Erstellen eines Index auf der status_id und ORDER_TYPE_ID Spalten

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

wird helfen, eine Menge, vor allem wenn es mehrere verschiedene Werte von status_id und ORDER_TYPE_ID in der ORDER_HEADER Tabelle.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top