2016-03-30 21 views
0

Müşterinin satın alım tarihi ve müşterinin son e-posta tıklama/açılış tarihi olan harici kaynaktan gelen iki veri setim var. Bu, sırasıyla iki tablo PURCHASE_INTER VE ACTIVITY_INTER tablolarında saklanır. Satın alma verileri birden fazla ve son satın alma tarihini almam gerekiyor. Ancak aktivite verileri her müşteri için benzersizdir. Veriler birbirinden bağımsızdır ve diğer veri grubu mevcut olmayabilir. İki tabloyu birleştiren, müşterinin dış kaynaktan gelen müşterinin kimliği olan ve tarihlerin en sonunu alan person_id bazında gruplandırdığımız, müşteri e-postasını almak için müşteri masamıza katıldığımız ve yine başka bir masaya katılacağımız bir sorgu oluşturduk. Bu verinin nihayetinde operasyonun eklendiğini veya güncellenip güncellenmediğini öğrenmek için depolanacağı yer. Bu sorgunun performansını nasıl geliştirebileceğimi önerebilir misiniz? Çok yavaş ve 10 saatten fazla sürüyor. PURCHASE_INTER AND ACTIVITY_INTER tablolarında milyonlarca kayıt var.Performansı iyileştirin

  • 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)

(ilk tw için:

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

Kopyaları kaldırmanız mı gerekiyor, yoksa "UNION" yerine "UNION ALL" kullanıyor musunuz? – jarlh

+0

Belirli bir iş ile kaç kayıt var? –

+0

Gerçekten 'RN' sütununu sağlamanız gerekiyor mu? Çok sayıda satır döndürürseniz bu hesaplamak pahalı olabilir. –

cevap

5

Sorgunuzda aşağıdaki dizinleri önerir o dizinler, eşleşme sayısı çok büyük olmadıkça ilk sütunun diğer ikiye göre daha büyük olması.)

Ayrıca, UNION değerini UNION ALL olarak değiştirin. UNION, kopyaları kaldırmak için ek yüke neden olur - ve bu her alt sorgu farklı sütunlar döndürdüğü için mümkün değildir (en azından iki alt sorgu arasında).

Ayrıca, ilk alt sorgu değiştirmek isteyebilirsiniz bir full outer join: toplama tabloları doğrudan yapılır çünkü

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 

Bu, Oracle optimizasyonu için daha fazla seçenek sunar - yapım endeksleri ve daha iyi istatistik işleme için kullanılabilir.

+0

Bu konuda yardımlarınız için teşekkürler. Gerçekten yardımcı oldu. Pek çok yeni şey öğrendim. –