2017-01-13 3 views
0

Grundsätzlich versuche ich eine "Vorschläge" -Seite basierend auf Benutzerinteressen zu erstellen.MySQL Unterabfrage in der gleichen Tabelle kills Leistung

In einer kumulativen Tabelle speichern ich alle Produkte, die von jedem Benutzer gesehen werden. Meine Idee war, alle gesehenen Produkte aller Menschen auszuwählen, die von mir gesehene Produkte besucht haben. Ich habe versucht, für eine Weile jetzt mit einer Abfrage zu kommen, aber meine beste Idee würde

  • a) Nur wenige Abfragen
  • b) Subqueries

Das Ding ist, ich denke, es zu tun mit Wenige Abfragen sind nicht skalierbar, wenn meine Tabelle wächst. Mit den Unterabfragen, die ich hatte, zerstörte die Abfrage meine Datenbank, obwohl, wenn ich EXPLAIN benutzte, alles in Ordnung schien (keine temporäre Tabelle, keine Plattentreffer), aber wenn ich die Abfrage aufraffte, dauerte es über eine Minute ... in einer Tabelle mit ~ 40k auszuführen Reihen. Die Abfragen nacheinander auszuführen, tat, was ich in weniger als einer Sekunde wollte, also bin ich wirklich verblüfft. Wo mache ich einen Fehler?

Die Tabelle, die die folgenden Spalten id (primary) hat, user_id, product_id und Haufen von nicht benötigten Felder

Hier finden Sie die SQL-Abfrage kam ich mit (das tötet meinen Server)

SELECT product_id 
FROM user_behavior 
WHERE user_id 
IN (

    SELECT user_id 
    FROM user_behavior 
    WHERE user_id <> 43456 
    AND product_id 
    IN (

     SELECT product_id 
     FROM user_behavior 
     WHERE user_id =43456 
     GROUP BY product_id 
    ) 
    AND offer_city_id 
    IN (0, 2) 
) 

wie ich laufen die Erträge der

| id | select_type   | table    | type    | possible_keys   | key  | key_len | ref  | rows  | Extra      | 
|---- |-------------------- |--------------- |---------------- |------------------- |--------- |--------- |------- |------- |-------------------------- | 
| 1  | PRIMARY    | user_behavior  | index    | NULL     | user_id | 8   | NULL  | 25800  | Using where; using index | 
| 2  | DEPENDENT SUBQUERY | user_behavior  | index_subquery | user_id,user_id_2  | user_id | 4   | func  | 3   | Using where    | 
| 3  | DEPENDENT SUBQUERY | user_behavior  | ref    | user_id,user_id_2  | user_id | 4   | const  | 76  | Using where; using index | 

EDIT folgende erklären: Es tut mir leid, ich kann nicht einen Tisch visualisieren :(

Antwort

1

Verwenden Sie nicht IN (SELECT ...).

Ich bin ziemlich verloren in was die Abfrage versucht zu tun, aber Wechsel zu JOIN und EXISTS ist wahrscheinlich ein Teil der Lösung. Vielleicht etwas in der Nähe dieser:

SELECT s.product_id 
    FROM user_behavior AS a 
    JOIN user_behavior AS b ON b.user_id = a.user_id 
    WHERE EXISTS (
       SELECT * 
        FROM user_behavior 
        WHERE product_id = b.product_id 
        AND user_id = 43456 
       ) 
     AND b.offer_city_id IN (0, 2) 
     AND b.user_id <> 43456 

und umfassen eine 'zusammengesetzte' INDEX(user_id, product_id) (in beliebiger Reihenfolge)

Oder vielleicht nur dies erforderlich ist ?? ...

SELECT DISTINCT product_id 
    FROM user_behavior AS b 
    WHERE EXISTS (
       SELECT * 
        FROM user_behavior 
        WHERE product_id = b.product_id 
        AND user_id = 43456 
       ) 
     AND offer_city_id IN (0, 2) 
     AND user_id <> 43456 

Nun, ich Ich hoffe, Sie bekommen einige Ideen von diesen Versuchen.

+0

Die zweite Abfrage war genau das, was ich brauchte. Ich habe keine Ahnung, wie genau EXISTS funktioniert, aber ich gehe zur MySQL-Dokumentation und versuche, sie zu verstehen. Vielen Dank! – Sk1ppeR

+0

'EXISTS' ist ein" Semi-Join "in dem es wie ein' JOIN' ist, aber stoppt wenn es eine Übereinstimmung findet. Dann gibt es nur Wahr oder Falsch zurück; Lass dich nicht von '*' täuschen. –

Verwandte Themen