Frage

Ich versuche, eine sehr alte Abfrage zu erhalten optimize, dass ich nicht um meinen Kopf wickeln kann. das Ergebnis, dass ich zu archivieren ist, dass ich den Besucher auf eine Web-Shop, was andere Kunden gezeigt Interesse empfehlen möchten haben, das heißt, was sie sonst mit dem Produkt gekauft haben gemeinsam, dass der Besucher auf sucht.

Ich habe eine Unterabfrage, aber es ist sehr langsam, nimmt ~ 15s auf ~ 8 000 000 Zeilen.

das Layout ist, dass alle Produkte, die in einem Korb-Benutzer sind, werden in einer Tabelle wsBasket gehalten und getrennt durch einen basketid (die in einer anderen Tabelle mit einem Element verbunden ist).

In diesem Beispiel möchte ich alle die beliebtesten Produkte aufzulisten, dass die Benutzer zusammen mit productid 427 gekauft haben, aber nicht die Liste productid 427 selbst.

SELECT productid, SUM(quantity) AS qty 
FROM wsBasket 
WHERE basketid IN 
    (SELECT basketid 
     FROM wsBasket 
     WHERE productid=427) AND productid!=427 
GROUP by productid 
ORDER BY qty 
DESC LIMIT 0,4;

Jede Hilfe ist sehr zu schätzen! hoffen, dass dies wenigstens jemand überhaupt Sinn macht:)

UPDATE 1: vielen Dank für Ihre Kommentare hier Jungs meine Antworten sind, werden sie im Kommentarfeld nicht passen.

Mit auf der obige Abfrage erläutert ich das fllowing bekam. Bitte beachten Sie, ich habe keine Indizes für die Tabelle (mit Ausnahme des Primärschlüssels auf dem id-Feld), ich mag die Abfrage profitiert von Indizes und Ort Indizes auf den richtigen Tasten ändern.

+----+--------------------+----------+------+---------------+------+---------+------+------+----------------------------------------------+
| id | select_type        | table    | type | possible_keys | key  | key_len | ref  | rows | Extra                                        |
+----+--------------------+----------+------+---------------+------+---------+------+------+----------------------------------------------+
|  1 | PRIMARY            | wsBasket | ALL  | NULL          | NULL | NULL    | NULL | 2821 | Using where; Using temporary; Using filesort |
|  2 | DEPENDENT SUBQUERY | wsBasket | ALL  | NULL          | NULL | NULL    | NULL | 2821 | Using where                                  |
+----+--------------------+----------+------+---------------+------+---------+------+------+----------------------------------------------+
War es hilfreich?

Lösung

Zwei offensichtliche Indizes hinzufügen: eine auf basketid und ein zweites auf productid: dann die Abfrage wiederholen und eine neue EXPLAIN zu sehen, dass die Indizes verwendet werden

Andere Tipps

Neben sicherzustellen, dass geeignete Indizes vorhanden auf productid und basketid, werden Sie häufig von Strukturierung profitieren Ihre Abfrage als eine einfache verbinden statt einer Unterabfrage, vor allem in MySQL.

SELECT b1.productid, SUM(b1.quantity) AS qty
FROM wsBasket AS b0
JOIN wsBasket AS b1 ON b1.basketid=b0.basketid
WHERE b0.productid=427 AND b1.productid<>427
GROUP BY b1.productid
ORDER BY qty DESC
LIMIT 4

Für mich auf einer möglicherweise ähnliche Datensatz der Join in zwei select_type: SIMPLE Zeilen in dem EXPLAIN Ausgang geführt, während die Unterabfrage Methode einen schrecklichen-for-Performance DEPENDENT SUBQUERY ausgespuckt. Folglich war die join weit über eine Größenordnung schneller.

Die beiden Felder, die Sie in erster Linie für die Suche in dieser Abfrage sind productid und basketid.

Wenn Sie nach Datensätzen suchen productid bis 427 gleich mit, Datenbank hat keine Ahnung, wo diese Platte zu finden. Es ist nicht einmal wissen, dass, wenn es eine passende findet, dass es nicht eine andere passende sein, so dass es durch die gesamte Tabelle zu suchen hat, möglicherweise Tausende von Datensätzen.

Ein Index wird eine separate Datei, die sortiert wird, und enthält nur das Feld / s sind Sie in der Sortierung auf Interesse. so der Erstellung eines Index spart eine immense Menge an Zeit!

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