Xrist1An
@Xrist1An
задаю глупые вопросы

Как правильно писать запросы для поиска по базе (MySQL) и не ронять сервер?

У меня есть база в которой около 70000 записей - музыка. Каждый трек относится к каким-то определенным жанрам.

Если песню можно отнести только к одному жанру (пусть будет trance), то для ее поиска я бы написал запрос через php следующего вида:

$result = mysql_query("SELECT * FROM music WHERE genre = 'trance'");


В поле genre для этого трека есть всего одно слово - trance, поэтому вроде как вполне быстро можно сделать выборку по всем таким трекам.

А вот если одна и так же композиция относится сразу к нескольким жанрам (пусть будет trance, house, electrohouse), то я пишу вот так:

$result = mysql_query("SELECT * FROM music WHERE genre LIKE '%trance%'");


Так как в поле genre для этого трека теперь уже 3 слова (trance, house, electrohouse), то приходится делать выборку через LIKE. Это уже ощутимо грузит сервер.

Как правильно в такой ситуации делать выборки? Я знаю, что есть sphinx, но для меня пока это сложновато. Как можно облегчить работу сервера на данном этапе, какие простйшие рекомендации вы можете дать?

Заранее спасибо!

UPD:

С изначальным вопросом я все понял, всем спасибо!

Теперь еще вопрос:

Если человек вводит запрос вида: "trance and house", то как правильно делать в таком случае выборку, чтобы в результате были выведены все треки, в жанрах которых встречаются слова из этого запроса? В данном случае должны вывестись все треки из жанра house и trance.

$result = mysql_query("SELECT * FROM xref_music WHERE genre_id = 7 OR genre_id = 5");


Цифры 7 и 5 - это соответственно id жанров trance и house.

Т.е. я беру строку trance and house, разбиваю ее по словам. А дальше? Как-нибудь убрать из нее все лишнее (and) и оставить только существующие жанры (house, trance)?

Потом загнать каждый жанр по отдельности в запрос как я показал в своем примере? Это по феншую будет?
  • Вопрос задан
  • 3315 просмотров
Решения вопроса 1
DmitriyEntelis
@DmitriyEntelis
Думаю за деньги
Почитайте про реляционные базы вообще и про третью нормальную форму в частности.
Не нужно хранить жанр музыки строкой для каждой композиции.
Заводим отдельную табличку
genre
---
genre_id
genre_title

Заводим табличку для указания соответствий
xref_music_genre
---
music_id
genre_id

Все.

UPD
Если человек вводит запрос вида: "trance and house", то как правильно делать в таком случае выборку, чтобы в результате были выведены все треки, в жанрах которых встречаются слова из этого запроса? В данном случае должны вывестись все треки из жанра house и trance.

select music_id 
from xref_music_genre 
where genre_id IN (5,7) 
group by music_id 
HAVING count(genre_id)=2
Ответ написан
Пригласить эксперта
Ответы на вопрос 3
FanatPHP
@FanatPHP
Чебуратор тега РНР
Дополню предыдущий ответ несколькими замечаниями.

Во-первых, сам запрос
SELECT m.* FROM genre g, music_genre mg,  music m
WHERE g.name = 'trance' AND mg.genre_id=g.id AND m.id=mg.music_id

Во-вторых, никаких mysql_query, только PDO. Код должен выглядеть так:
$sql = "SELECT m.* FROM genre g, music_genre mg,  music m
WHERE g.name = ? AND mg.genre_id=g.id AND m.id=mg.music_id";
$stmt = $pdo->prepare($sql);
$stmt->execute([$search]);
$allmusic = $stmt->fetchAll();

В-третьих, обе колонки в music_genre должны быть проиндексированы. или даже так - два индекса, один из которых "music_id, genre_id", а второй - "genre_id, music_id"
Ну и на genre.name тоже можно повесить, уникальный
Ответ написан
Xrist1An
@Xrist1An Автор вопроса
задаю глупые вопросы
С изначальным вопрос я все понял, всем спасибо!

Теперь еще вопрос:

Если человек вводит запрос вида: "trance and house", то как правильно делать в таком случае выборку, чтобы в результате были выведены все треки, в жанрах которых встречаются слова из этого запроса? В данном случае должны вывестись все треки из жанра house и trance.

$result = mysql_query("SELECT * FROM xref_music WHERE genre_id = 7 OR genre_id = 5");


Цифры 7 и 5 - это соответственно id жанров trance и house.

Т.е. я беру строку trance and house, разбиваю ее по словам. А дальше? Как-нибудь убрать из нее все лишнее (and) и оставить только существующие жанры (house, trance)?

Потом загнать каждый жанр по отдельности в запрос как я показал в своем примере? Это по феншую будет?
Ответ написан
TheCreator
@TheCreator
Бездельник
А вообще, если не собираетесь часто менять жанры, лучше всего использовать поле типа SET, оно для того и создано, чтобы хранить определенное количество фиксированных значений. Создавать для этого отдельную таблицу, мне кажется, перебор. И потом с помощью оператора FIND_IN_SET() можно делать любые выборки, поставив индекс на это поле всё будет выбираться мгновенно.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы