Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Langsame MySQL-Abfrage:JOIN + mehrere WHERE + ORDER BY

Indizes machen einen massiven Unterschied in MySQL, eine Abfrage, die 15 Minuten mit einem falschen Satz von Indizes dauerte, dauerte 0,2 Sekunden mit den richtigen, aber das Finden der richtigen Balance ist im Allgemeinen das Problem. Natürlich ist es ohne einige Beispieldaten wirklich schwer zu sagen, ob die folgende Lösung Ihnen Zeit sparen wird, aber theoretisch sollte es das tun.

Um Ihre Fragen zu beantworten, würde ich die Tabellen wie folgt umgestalten:

CREATE TABLE `product_all` ( 
`prod_id` INT( 10 ) NOT NULL, 
`ref_id` INT( 10) NOT NULL, 
`date` DATE NOT NULL , 
`buy_link` BLOB NOT NULL , 
`sale_price` FLOAT NOT NULL,
PRIMARY KEY (prod_id, ref_id) ,
INDEX date_Index (`date` ASC),
UNIQUE INDEX prod_price_Index (prod_id ASC, sale_price ASC)
) ENGINE = MYISAM ; 


CREATE TABLE `product_info` ( 
`prod_id` INT( 10 ) NOT NULL AUTO_INCREMENT, 
`prod_name` VARCHAR( 200 ) NOT NULL, 
`brand` VARCHAR( 50 ) NOT NULL, 
`retail_price` FLOAT NOT NULL, 
`category` INT( 3 ) NOT NULL, 
`gender` VARCHAR( 1 ) NOT NULL, 
`type` VARCHAR( 10 ) NOT NULL,
PRIMARY KEY (prod_id) ,
UNIQUE INDEX prod_id_name_Index (prod_id ASC, prod_name ASC),
INDEX category_Index (category ASC),
INDEX gender_Index (gender ASC)
) ENGINE = MYISAM ;

SELECT product_info.*, MIN(product_all.sale_price) as sale_price, product_all.buy_link         
FROM product_info         
NATURAL JOIN (SELECT * FROM product_all WHERE product_all.date = '2010-09-30') as product_all         
WHERE (product_info.category = 2           
AND product_info.gender = 'W' )         
GROUP BY product_all.prod_id         
ORDER BY MIN(product_all.sale_price) ASC LIMIT 13        

Der Leistungsgewinn hier wird erzielt, indem ich die Hauptfelder indiziere, die verknüpft werden und in der where-Klausel enthalten sind. Persönlich würde ich Ihrer ersten Abfrage folgen, wenn Sie darüber nachdenken, was besser funktionieren sollte.

Soweit ich verstehe, was in der ersten und zweiten Abfrage passiert:

  • Die erste Abfrage wird durch eine Unterabfrage gefiltert, bevor sie die natürliche Verknüpfung durchführt, das bedeutet, dass sie nur in den resultierenden Daten und nicht in der gesamten Tabelle verknüpft wird.
  • Die zweite Abfrage verbindet die gesamte zweite Tabelle und filtert dann die resultierenden Zeilen des gesamten Loses zurück zu dem, was Sie wollen.

Als Faustregel sollten Sie normalerweise Indizes zu Ihren wichtigsten Verknüpfungsfeldern und auch zu den Feldern hinzufügen, die Sie in where-Klauseln am häufigsten verwenden. Ich habe auch einigen der Felder, die Sie regelmäßig abfragen möchten, einige eindeutige Indizes hinzugefügt, z. B. prod_id_name_Index.

Wenn dies Ihre Leistung nicht verbessert, könnten Sie vielleicht einige Dummy-Daten zum Spielen posten, damit ich vielleicht eine schnellere Lösung bekommen kann, die ich bewerten kann.

Hier ist ein Artikel, der die Indizierung für Leistung in MySQL durchgeht, lesenswert, wenn Sie mehr wissen möchten.

Viel Glück!

BEARBEITEN:Ihre letzte Frage, die ich beim ersten Mal übersehen habe, ist die Antwort, dass, wenn Sie die Hauptverbindungsfelder indizieren, sich das ändert, wo sich die Gesamtleistung nur geringfügig auswirkt, aber die eindeutigen Indizes, die ich in die Tabellen eingefügt habe, sollten dies berücksichtigen die meisten Dinge, auf denen Sie Abfragen basieren möchten. Das Wichtigste, woran Sie denken sollten, ist, wenn Sie ein Feld häufig abfragen oder verknüpfen, sollte es wirklich indiziert werden, aber kleinere Abfragen und Änderungen der Reihenfolge durch Sie sollten sich im Hinblick auf die Neuausrichtung Ihrer Indexierungsstrategie einfach keine Gedanken machen.