2010-06-28 3 views
0

J'essaie d'optimiser une très vieille requête que je ne peux pas enrouler ma tête autour. Le résultat que je veux archiver est que je veux recommander au visiteur sur une boutique en ligne ce que d'autres clients ont montré d'intérêt, c'est-à-dire ce qu'ils ont acheté d'autre avec le produit que le visiteur regarde.requête pour ce que les clients ont acheté avec le produit listé

J'ai une sous-requête mais c'est très lente, prend ~ 15s sur ~ 8 000 000 lignes.

la mise en page est que tous les produits qui sont mis dans un panier d'utilisateurs sont conservés dans un tableau wsBasket et séparés par un basketid (qui dans une autre table est associée à un membre).

Dans cet exemple, je souhaite répertorier tous les produits les plus populaires que les utilisateurs ont achetés avec le produit 427, mais pas le produit 427 lui-même.

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; 

toute aide est très appréciée! espérons que cela a un sens tout au moins une personne :)

 

MISE À JOUR 1: Merci pour vos commentaires les gars ici sont mes réponses, ils ne correspondaient pas aux commentaires sur le terrain. En utilisant EXPLAIN sur la question ci-dessus j'ai eu le fllowing. S'il vous plaît noter, je n'ai pas d'index sur la table (sauf pour la clé primaire sur le champ id), je veux modifier la requête pour bénéficier des index et placer des index sur les bonnes clés.

+----+--------------------+----------+------+---------------+------+---------+------+------+----------------------------------------------+ 
| 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         | 
+----+--------------------+----------+------+---------------+------+---------+------+------+----------------------------------------------+ 
+0

Quels index avez-vous sur la table wsBasket? et qu'obtenez-vous lorsque vous exécutez un EXPLAIN sur la requête? –

+0

À quoi ressemblent vos index? Sachant que cela pourrait faciliter la modification de la requête pour vous. – MJB

Répondre

1

Deux indices évidents pour ajouter: un sur basketid et une seconde sur ProductID: puis retenter la requête et une nouvelle EXPLAIN pour voir que les indices sont utilisés

+0

qui a fait l'affaire, ~ 0.124 pour une requête maintenant!:) et je cherchais des index combinés et modifiais la requête, bien. Merci! existe-t-il un moyen d'éviter la sous-requête? – johan

+0

Les index combinés/composites peuvent être utiles pour d'autres requêtes sur cette table, mais vous seul savez quels autres types de requêtes sont exécutés, donc nous ne pouvons pas vous aider sans plus d'informations ... mais je soupçonne que ces deux index aideront autres zones du code d'application ainsi –

+0

Voir la réponse de bobince pour modifier la requête –

0

Les deux champs que vous utilisez principalement pour la recherche dans cette requête sont productid et basketid.

Lorsque vous recherchez des enregistrements dont le paramètre est égal à 427, Database ne sait pas où trouver cet enregistrement. Il ne sait même pas que s'il trouve un correspondant, qu'il n'y en aura pas un autre, il doit donc parcourir toute la table, potentiellement des milliers d'enregistrements. Un index est un fichier séparé qui est trié et contient uniquement le ou les champs que vous souhaitez trier. Créer un index permet donc d'économiser énormément de temps!

1

En plus de garantir que les index appropriés existent sur productid et basketid, vous bénéficierez souvent de la structuration de votre requête en une simple jointure plutôt qu'en une sous-requête, en particulier dans 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 

Pour moi, sur un ensemble de données peut-similaire, la jointure a donné lieu à deux select_type: SIMPLE lignes de la sortie EXPLAIN, alors que la méthode sous-requête a craché une horrible performance pour DEPENDENT SUBQUERY. Par conséquent, la jointure était bien supérieure à un ordre de grandeur plus rapidement.

+0

+1 pour la requête de jointure –

Questions connexes