Cette requête MySQL fonctionne très bienMySQL Syntaxe et « OR » Performance
SELECT o.id
FROM descriptions_programs d, titles_programs t, programs o
WHERE (d.object_id=o.id
AND MATCH (d.text) AGAINST ('+china' IN BOOLEAN MODE)
AND d.current=1)
AND (t.object_id=o.id
AND MATCH (t.text) AGAINST ('+china' IN BOOLEAN MODE)
AND t.current=1)
Mais si je remplace un ET avec un OU, la requête est exécutée très longtemps. (Je dois le tuer.):
SELECT o.id
FROM descriptions_programs d, titles_programs t, programs o
WHERE (d.object_id=o.id
AND MATCH (d.text) AGAINST ('+china' IN BOOLEAN MODE)
AND d.current=1)
OR (t.object_id=o.id
AND MATCH (t.text) AGAINST ('+china' IN BOOLEAN MODE)
AND t.current=1)
Pourquoi est-ce? Ne soyez pas accroché à la simplicité de + Chine. Je viens de simplifier cela pour le débogage. De plus, si je cours avec juste un des tests MATCH AGAINST, cela fonctionne bien, donc les deux sont corrects par eux-mêmes. J'ai l'impression que je provoque involontairement une énorme adhésion en utilisant OR, mais je ne comprends tout simplement pas. J'utilisais auparavant un test IN sur une UNION de deux sous-sélections et cela fonctionnait aussi. Droite?
Mise à jour: par demande de bobince. Ce n'est pas super lent, mais à ~ 500ms, ce n'est pas aussi rapide que d'utiliser UNION comme discussed here.
mysql> explain SELECT o.id
-> FROM programs o
-> JOIN titles_programs t ON t.object_id=o.id
-> JOIN descriptions_programs d ON d.object_id=o.id
-> WHERE MATCH (d.text) AGAINST ('+china' IN BOOLEAN MODE) AND d.current=1
-> OR MATCH (t.text) AGAINST ('+china' IN BOOLEAN MODE) AND t.current=1
-> ;
+----+-------------+-------+-------+
----------------+----------------+---------+----------------------+--------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+----------------+----------------+---------+----------------------+--------+-------------+
| 1 | SIMPLE | o | index | PRIMARY | PRIMARY | 4 | NULL | 148666 | Using index |
| 1 | SIMPLE | d | ref | object_current | object_current | 4 | haystack.o.id | 1 | |
| 1 | SIMPLE | t | ref | object_current | object_current | 4 | haystack.d.object_id | 1 | Using where |
+----+-------------+-------+-------+----------------+----------------+---------+----------------------+--------+-------------+
Toujours pas de différence. Fonctionne pendant> 1 minute avant que je doive le tuer. Changez le OU en ET, et il s'exécute en millisecondes. Même si vous supprimez l'une des deux phrases MATCH AGAINST. –
Essayez d'exécuter uniquement la table 't'. Éliminer 'd' à la fois les clauses "FROM" et "WHERE". Alors quel est le temps de course? Si la réponse est «ça prend une éternité», alors ce n'est pas une question de «OU», c'est juste que la numérisation des tables est vraiment lente. –
Vous devez faire attention à ce que "OU" vous changez pour un "ET": ou vous obtenez le comportement t * d. Aussi, vous devriez mettre des parenthèses en cas d'ambiguïté: je ne sais pas ce que la convention MySQL est, mais si vous dites "foo et bar ou voiture" alors cela pourrait signifier "(foo et bar) ou voiture" ce qui est mauvais! –