2016-08-05 13 views
0

Hallo Ich habe eine Produktkategorie Datenbank, wo Produkte und Kategorien haben eine viele zu viele Beziehung mit einer dritten Tabelle z. Produktkategorie. Nun läuft Im eine Abfrage auf der Datenbank, um alle Produkte zu holen, die eine Kategorie auf einer Reihe von Kategorie-IDs gegeben gehören, können Sie das folgende Beispiel sehen:Mysql GROUP BY Optimierung mit inneren Joins und große Datenmenge

SELECT * FROM products p JOIN product_category pc ON p.id = pc.product_id 
WHERE pc.category_id IN (1,2,3,4,5,6) GROUP BY p.id LIMIT 0,40 

Die Produkte Tisch haves um 23k Zeilen und die Tabelle product_category 26k Zeilen.

Normalerweise hat das Array der Kategorie IDs in der WHERE IN-Klausel viel mehr Elemente.

Jetzt dauert diese Abfrage 300ms, um die Ergebnisse zu holen. Wenn ich die GROUP BY-Klausel entferne, dauert die Abfrage nur 2ms, um die Ergebnisse abzurufen.

Eine vollständigere Abfrage lautet wie folgt:

select * from `products` inner join `product_category` on `products`.`id` = `product_category`.`product_id` 
     where `product_category`.`category_id` in ('1', '2', '3', '4', '5', '6', '7', 
    '8', '44', '155', '156', '157', '158', '159', '160', '161', '162', '168', '169', '171', '172', '173', '174', '175', '176', 
    '178', '179', '180', '181', '182', '183', '184', '185', '186', '189', '190', '191', '192', '193', '194', '195', '196', 
    '197', '198', '199', '200', '201', '202', '203', '204', '205', '206', '207', '208', '209', '213', '215', '216', '217', 
    '218', '219', '230', '231', '232', '233', 
    '234', '235', '236', '237', '240', '241', 
    '242', '243', '244', '245', '246', '247', 
    '248', '249', '250', '251', '252', '253', 
    '254', '255', '256', '257', '258', '259', 
    '260', '261', '325', '326', '327', '328', 
    '334', '335', '336', '337', '338', '339', '340', '341', '342', '343', '344') and `products`.`is_visible` = '1' 
    group by `product_category`.`product_id` 
    order by `popularity` desc, `popularity` desc limit 40 offset 0 

Die Erklärung der Abfrage lautet wie folgt:

Explain of the query

So ist meine Frage, ob es einen Weg gibt, das zu optimieren Fragen Sie gezielt die Gruppe ab, damit es nicht zu lange dauert, bis die Ergebnisse geladen sind.

+0

Da Sie nicht aggregieren, haben Sie stattdessen 'SELECT DISTINCT p. *' Versucht? – Uueerdo

+0

@Uueerdo Ja, ich habe, ohne Änderung, die Abfrage mit Select Distinct dauert mehr oder weniger die gleiche Zeit, die mit der Gruppe von. Danke – asolenzal

+0

Yo sollte diese Gruppe niemals nach Struktur verwenden, da es nicht garantiert ist, immer die gleichen Ergebnisse in den Feldern zu liefern, die Sie in der Gruppe nicht angegeben haben. Nur weil du etwas tun kannst, heißt das nicht, dass du es tun solltest. Benutze die richtige Gruppe, wie jede andere Datenbank es erfordert. Verwenden Sie auch nie SELECT *, wenn Sie eine Verknüpfung haben, da sie mehr Daten zurückgibt, als Sie benötigen (die Join-Felder werden wiederholt), was zur Langsamkeit der Abfrage beiträgt. Bei beiden Syntaxproblemen handelt es sich um SQL-Antipatterns, und Sie würden die Code-Überprüfung verpuffen, wenn Sie versuchen, sie von jemandem zu übergeben, der Datenbanken wirklich versteht. – HLGEM

Antwort

0

Wie ich in dem Kommentar sagte, könnten Sie etwas Glück mit SELECT DISTINCT p.* haben; aber ich in der Regel sehen die Menschen GROUP BY mit um DISTINCT Langsamkeit zu bekommen ...

Eine weitere Option ist eine Unterabfrage anstelle einer direkten JOIN, etwa so:

SELECT * 
FROM `products` 
WHERE id IN (
    SELECT DISTINCT `product_id` 
    FROM `product_category` 
    WHERE `category_id` IN ([category id list]) 
) 
AND `is_visible` = '1' 
ORDER BY `popularity` DESC, `popularity` DESC 
LIMIT 40 OFFSET 0 

oder

SELECT p.* 
FROM `products` AS p 
INNER JOIN (
    SELECT DISTINCT `product_id` 
    FROM `product_category` 
    WHERE `category_id` IN ([category id list]) 
) AS pcSmry ON p.id = pcSmry.product_id 
WHERE p.`is_visible` = '1' 
ORDER BY `popularity` DESC, `popularity` DESC 
LIMIT 40 OFFSET 0 

BEARBEITEN: Wenn keiner von diesen hilft, möchten Sie wahrscheinlich in die Indexierung der Felder in WHERE und ON Bedingungen suchen.