Frage

Ok, hier ist eine Abfrage, die ich jetzt auf einem Tisch leite die 45.000 Datensätze und ist 65 MB groß ... und ist nur über eine größere Ansicht zu erhalten und größer (so muss ich auf die zukünftige Entwicklung denken auch hier ):

SELECT count(payment_id) as signup_count, sum(amount) as signup_amount
FROM payments p
WHERE tm_completed BETWEEN '2009-05-01' AND '2009-05-30'
AND completed > 0
AND tm_completed IS NOT NULL
AND member_id NOT IN (SELECT p2.member_id FROM payments p2 WHERE p2.completed=1 AND p2.tm_completed < '2009-05-01' AND p2.tm_completed IS NOT NULL GROUP BY p2.member_id)

Und wie Sie vielleicht oder vielleicht nicht vorstellen - es drosselt den MySQL-Server zum Erliegen ...

Was sie tut, ist - es ist einfach die Anzahl der neuen Benutzer zieht die unterschrieben haben mindestens ein „abgeschlossen“ Zahlung, tm_completed nicht leer ist (da es nur für abgeschlossene Zahlungen aufgefüllt wird), und (das eingebettete Select) das Mitglied hat noch nie eine „abgeschlossen“ Zahlung vor - das heißt, er ist ein neues Mitglied (nur, weil das System tut rebills und so weiter, und dies ist die einzige Möglichkeit, zwischen einem bestehenden Mitglied zu Art zu unterscheiden, der gerade rebilled und ein neues Mitglied, wurde zum ersten Mal in Rechnung gestellt).

Nun ist es eine Möglichkeit, diese Abfrage zu optimieren weniger Ressourcen zu verwenden, oder etwas, und meine mysql Ressource zu nehmen zu stoppen auf den Knie ...?

Fehle ich irgendwelche Informationen dieses weiter zu klären? Lassen Sie mich wissen ...

EDIT:

Hier sind die Indizes bereits auf dieser Tabelle:

Primär Primär 46757 payment_id

member_id INDEX 23378 member_id

payer_id INDEX 11689 payer_id

coupon_id INDEX 1 coupon_id

tm_added INDEX 46757 tm_added, product_id

tm_completed INDEX 46757 tm_completed, product_id

War es hilfreich?

Lösung

Diese Art von IN Unterabfragen sind ein bisschen langsam in MySQL. Ich würde es so neu formulieren:

SELECT COUNT(1) AS signup_count, SUM(amount) AS signup_amount
FROM   payments p
WHERE  tm_completed BETWEEN '2009-05-01' AND '2009-05-30'
AND    completed > 0
AND    NOT EXISTS (
           SELECT member_id
           FROM   payments
           WHERE  member_id = p.member_id
           AND    completed = 1
           AND    tm_completed < '2009-05-01');

Die ‚tm_completed IS NOT NULL‘ Prüfung ist nicht erforderlich, da die von Ihrem BETWEEN Zustand impliziert wird.

Auch stellen Sie sicher, Sie haben einen Index auf:

(tm_completed, completed)

Andere Tipps

Ich hatte Spaß, diese Lösung die Zusammenstellung, die keine Unterabfrage benötigt:

SELECT count(p1.payment_id) as signup_count, 
       sum(p1.amount)       as signup_amount  

  FROM payments p1
       LEFT JOIN payments p2 
       ON p1.member_id = p2.member_id
   AND p2.completed = 1
   AND p2.tm_completed < date '2009-05-01'

 WHERE p1.completed > 0
   AND p1.tm_completed between date '2009-05-01' and date '2009-05-30'
   AND p2.member_id IS NULL;

Vermeiden Sie mit einer Unterabfrage mit IN; MySQL unterstützt optimiert diese nicht gut (obwohl es anstehende Optimierungen in 5.4 und 6.0 in Bezug auf diesen (siehe hier ) Umschreiben dies als Join werden Sie wahrscheinlich erhalten eine Leistungssteigerung.

SELECT count(payment_id) as signup_count, sum(amount) as signup_amount
FROM payments p
LEFT JOIN (SELECT p2.member_id
          FROM payments p2
          WHERE p2.completed=1
          AND p2.tm_completed < '2009-05-01'
          AND p2.tm_completed IS NOT NULL
          GROUP BY p2.member_id) foo
ON p.member_id = foo.member_id AND foo.member_id IS NULL
WHERE tm_completed BETWEEN '2009-05-01' AND '2009-05-30'
AND completed > 0
AND tm_completed IS NOT NULL

Zweitens würde ich Ihr Tabellenschema sehen; verwenden Sie Indizes?

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