Objectif: Proposer des objets en fonction des choix de l'utilisateurMySQL: objets Suggérant (optimisation d'une requête multi-jointure)
données: Tableau contenant les informations sur la façon dont les utilisateurs commanderaient un sous-ensemble d'objets du pire au meilleur; Exemple:
1 2 3 4 5 6
John: A B G J S O
Mary: A C G L
Joan: B C L J K
Stan: G J C L
Il y a environ 20 fois plus d'utilisateurs que d'objets, la gamme de chaque utilisateur contient 50 à 200 objets.
Le tableau:
CREATE TABLE IF NOT EXISTS `pref` (
`usr` int(10) unsigned NOT NULL,
`obj` int(10) unsigned NOT NULL,
`ord` int(10) unsigned NOT NULL,
UNIQUE KEY `u_o` (`usr`,`obj`),
KEY `u` (`usr`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
idée de base: Itérer à l'intérieur des objets de l'utilisateur à partir de la deuxième pire, des paires de construction (A> B); Recherchez-les dans les files d'attente des autres utilisateurs et répertoriez les éléments mieux que A selon ces utilisateurs.
Query:
SELECT e.obj, COUNT(e.obj) AS rate
FROM pref a, pref b, pref c, pref d, pref e
WHERE a.usr = '222' # step 1: select a pair of objects A, B, where A is better than B according to user X
AND a.obj = '111'
AND b.usr = a.usr
AND b.ord < a.ord
AND c.obj = a.obj # step 2: find users thinking that object A is better than B
AND d.obj = b.obj
AND d.ord < c.ord
AND d.usr = c.usr
AND e.ord > c.ord # step 3: find objects better than A according to these users
AND e.usr = c.usr
GROUP BY e.obj
ORDER BY rate DESC;
Alias:
a
objet A ('111'), l'utilisateur courant ('222')
b
objet B, pire qu'un après l'utilisateur courant (a plus faible valeur de « ord » de A)
c
objet A dans la gamme d'un autre utilisateur
d
objet B dans la gamme d'un autre utilisateur
e
objet mieux que A dans la gamme d'autres utilisateurs
Le plan d'exécution (Ouo et uo étant les indices comme suggéré par Quassnoi):
+----+-------------+-------+------+---------------+------+---------+---------------------+------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+---------------------+------+----------------------------------------------+
| 1 | SIMPLE | a | ref | ouo,uo | ouo | 8 | const,const | 1 | Using index; Using temporary; Using filesort |
| 1 | SIMPLE | b | ref | ouo,uo | uo | 4 | const | 86 | Using where |
| 1 | SIMPLE | d | ref | ouo,uo | ouo | 4 | db.b.obj | 587 | Using index |
| 1 | SIMPLE | c | ref | ouo,uo | ouo | 8 | const,db.d.usr | 1 | Using where; Using index |
| 1 | SIMPLE | e | ref | uo | uo | 4 | db.d.usr | 80 | Using where |
+----+-------------+-------+------+---------------+------+---------+---------------------+------+----------------------------------------------+
La requête semble bien fonctionner aussi longtemps que la l'ensemble de données n'est pas trop grand; des idées sur la façon de le rationaliser pour soutenir de plus grands ensembles de données?
Combien d'objets par utilisateur y aura-t-il en moyenne? – Quassnoi
Environ 50-200 objets par utilisateur. – Mike
Avez-vous vraiment besoin de ce classement exactement comme il est maintenant? La requête pourrait être facilement améliorée si ce n'est pour ce classement.Aussi, pourriez-vous s'il vous plaît poster le plan d'exécution de la requête? – Quassnoi