MySQL - Найти строки, соответствующие всем строкам из объединенной таблицы - PullRequest
0 голосов
/ 07 августа 2009

Таблица 1: Треки

Таблица 2: Список слов

Таблица 3: N: M В треке есть слова (слова трека)

Найти все треки, в которых есть все слова.

В настоящее время запрос выглядит так:

SELECT DISTINCT t.id FROM track as t
Left Join trackwords as tw ON t.id=tw.trackid
Left Join wordlist as wl on wl.id=tw.wordid
WHERE 
wl.trackusecount>0 
group by t.id
HAVING SUM(IF(wl.word IN ('folsom','prison','blues'),1,0)) = 3;

Который согласно EXPLAIN использует все индексы, необходимые:

+----+-------------+-------+--------+-----------------------+---------+---------+----------------+---------+-------------+
| id | select_type | table | type   | possible_keys         | key     | key_len | ref            | rows    | Extra       |
+----+-------------+-------+--------+-----------------------+---------+---------+----------------+---------+-------------+
|  1 | SIMPLE      | t     | index  | PRIMARY               | PRIMARY | 4       | NULL           | 8194507 | Using index | 
|  1 | SIMPLE      | tw    | ref    | wordid,trackid        | trackid | 4       | mbdb.t.id      |       3 | Using where | 
|  1 | SIMPLE      | wl    | eq_ref | PRIMARY,trackusecount | PRIMARY | 4       | mbdb.tw.wordid |       1 | Using where | 
+----+-------------+-------+--------+-----------------------+---------+---------+----------------+---------+-------------+

Но запрос занимает много времени. Любое предложение по ускорению запроса?

Ответы [ 3 ]

5 голосов
/ 07 августа 2009

Нет смысла в левом соединении, если вы ищете только треки, в которых есть все слова. Я предполагаю, что комбинация (trackid, wordid) является уникальной в trackwords.

SELECT t.id
  FROM track as t,  trackwords as tw, wordlist as wl
 WHERE t.id=tw.trackid
   AND wl.id=tw.wordid
   AND wl.trackusecount>0 /* not sure what that is - you have it in your query */
   AND wl.word in ('folsom','prison','blues')
 GROUP by t.id
HAVING count(*) = 3

Для этого запроса будут использованы индексы по списку слов (word), трек-словам (trackid, wordid) и треку (id).

3 голосов
/ 07 августа 2009

Ваш набор задач очень похож на проблему хранения тегов для таких элементов, как StackOverflow или Del.icio.us.

Статья Теги: схемы базы данных предлагает несколько решений, среди которых идея @ ChssPly76.

0 голосов
/ 07 августа 2009

Вероятно, будет быстрее, если разбить это на два запроса. Во-первых, соединение слов и треквордов, чтобы получить все треки, которые вам нужны. Затем вернитесь к таблице треков и выполните:

WHERE t.id IN(...trackids here...)

, но, в первую очередь, вы возвращаете запрос t.id, который у вас уже есть в tw.trackid.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...