2016-03-30 11 views
0

Ich habe zwei Sätze von Daten aus externer Quelle - Kaufdatum des Kunden und letzte E-Mail Klick/Öffnen Sie das Datum des Kunden. Dies wird in zwei Tabellen PURCHASE_INTER und ACTIVITY_INTER gespeichert. Kaufdaten sind mehrfach und ich muss das letzte Kaufdatum abholen. Die Aktivitätsdaten sind jedoch für jeden Kunden eindeutig. Die Daten sind voneinander unabhängig und andere Daten sind möglicherweise nicht vorhanden. Wir haben unten Abfrage geschrieben, die zwei Tabellen kombiniert, gruppiert sie auf person_id, die ID des Kunden ist, der von der externen Quelle kommt und das späteste der Daten erhält, tritt mit unserer Kundentabelle bei, um die Kundenemail zu erhalten, und tritt wieder mit einer anderen Tabelle bei wo diese Daten letztendlich gespeichert werden, um zu wissen, ob es Einfüge- oder Aktualisierungsoperation ist. Könnten Sie mir bitte vorschlagen, wie ich die Leistung dieser Abfrage verbessern kann? Es ist schrecklich langsam und dauert mehr als 10 Stunden. In den Tabellen PURCHASE_INTER und ACTIVITY_INTER sind Millionen von Datensätzen enthalten.Verbessern Sie die Leistung

SELECT INTER.*, C.ID AS CUSTOMER_ID, C.EMAIL AS CUSTOMER_EMAIL, LSI.ID AS INTERACTION_ID, ROW_NUMBER() OVER (ORDER BY PERSON_ID ASC) AS RN FROM (
    SELECT PERSON_ID    AS PERSON_ID, 
     MAX(LAST_CLICK_DATE) AS LAST_CLICK_DATE, 
     MAX(LAST_OPEN_DATE)  AS LAST_OPEN_DATE, 
     MAX(LAST_PURCHASE_DATE) AS LAST_PURCHASE_DATE 
    FROM (
    SELECT ACT.PERSON_ID AS PERSON_ID, 
      ACT.LAST_CLICK_DATE AS LAST_CLICK_DATE, 
      ACT.LAST_OPEN_DATE AS LAST_OPEN_DATE, 
      NULL AS LAST_PURCHASE_DATE 
    FROM ACTIVITY_INTER ACT 
    WHERE ACT.JOB_ID = 77318317 
    UNION 
    SELECT PUR.PERSON_ID AS PERSON_ID, 
      NULL AS LAST_CLICK_DATE, 
      NULL AS LAST_OPEN_DATE, 
      PUR.LAST_PURCHASE_DATE AS LAST_PURCHASE_DATE 
    FROM PURCHASE_INTER PUR 
    WHERE PUR.JOB_ID = 77318317 
    ) GROUP BY PERSON_ID 
) INTER LEFT JOIN CUSTOMER C ON INTER.PERSON_ID = C.PERSON_ID 
     LEFT JOIN INTERACTION LSI ON C.ID = LSI.CUSTOMER_ID; 
+0

Müssen Sie Duplikate entfernen, oder können Sie "UNION ALL" anstelle von "UNION" verwenden? – jarlh

+0

Wie viele Datensätze entsprechen einem bestimmten Job? –

+0

Müssen Sie wirklich die Spalte "RN" bereitstellen? Wenn Sie eine große Anzahl von Zeilen zurückgeben, kann das eine hohe Rechenleistung erfordern. –

Antwort

5

Ihre Abfrage schlägt folgende Indizes:

  • ACTIVITY_INTER(JOB_ID, PERSON_ID, LAST_CLICK_DATE, LAST_OPEN_DATE)
  • PURCHASE_INTER(JOB_ID, PERSON_ID, LAST_PURCHASE_DATE)
  • CUSTOMER(PERSON_ID)
  • INTERACTION(CUSTOMER_ID)

(Zum ersten tw o Indizes, ist die erste Spalte wichtiger als die beiden anderen, es sei denn, die Anzahl der Spiele sehr groß ist.)

Ändern Sie auch die UNION-UNION ALL. UNION verursacht Overhead zum Entfernen von Duplikaten - und dies ist nicht möglich (zumindest zwischen den beiden Unterabfragen), da jede Unterabfrage unterschiedliche Spalten zurückgibt.

Darüber hinaus sollten Sie die erste Unterabfrage mit einem ersetzen full outer join:

SELECT COALESCE(a.PERSON_ID, p.PERSON_ID) as PERSON_ID, 
     a.LAST_CLICK_DATE, a.LAST_OPEN_DATE,p.LAST_PURCHASE_DATE 
FROM (SELECT ACT.PERSON_ID AS PERSON_ID, 
      MAX(ACT.LAST_CLICK_DATE) AS LAST_CLICK_DATE, 
      MAX(ACT.LAST_OPEN_DATE) AS LAST_OPEN_DATE 
     FROM ACTIVITY_INTER ACT 
     WHERE ACT.JOB_ID = 77318317 
     GROUP BY ACT.PERSON_ID 
    ) a FULL OUTER JOIN 
    (SELECT PUR.PERSON_ID AS PERSON_ID, 
      MAX(PUR.LAST_PURCHASE_DATE) AS LAST_PURCHASE_DATE 
     FROM PURCHASE_INTER PUR 
     WHERE PUR.JOB_ID = 77318317 
     GROUP BY PER.PERSON_ID 
    ) p 
    ON a.PERSON_ID = p.PERSON_ID 

Dies gibt Oracle mehr Möglichkeiten zur Optimierung, da die Aggregation direkt auf den Tischen durchgeführt wird - machen Indizes und bessere Statistiken verfügbar für die Verarbeitung.

+0

Vielen Dank für Ihre Hilfe zu diesem Thema. Es war sehr hilfreich. Ich habe viele neue Dinge gelernt. –

Verwandte Themen