нужна простая выборка из 2-х больших таблиц

ну дык..
1. делаешь составной индекс на films: films_rating_id_idx (rating, id)
2. запрос переписываешь так:
Код:
SELECT *
FROM product
JOIN cat ON cat.product_id = product.id
WHERE cat.id= 666 AND rating > 10 AND id > 20 -- конкретные значения передаются извне
ORDER BY rating ASC, id
LIMIT 20
3. поскольку mysql не умеет работать с окнами (aka COUNT(*) OVER() в postgresl или oracle), общее кол-во (правда, по ходу, примерное) берёшь из explain этого запроса..

вообще, имхо, для таких объемов и задачь лучше посмотреть в сторону более серьезных субд.. той же postgresql, например.. поверь, гимор с переходом сто раз окупится..
 
так, стоп!.. как это я проглядел.. признаться на таблицу genre_connect вообще не посмотрел (т.к. не фигурирует в запросе)..
genre_connect.genre_id int(11) NOT NULL и films.genre_ids text NOT NULL..
это что?.. что-то опять недоговариваешь?.. как в действительности(!) делается выборка?.. при чем тут вообще "product"?.. О_о
 
product - не обращай внимания. Это я так назвал таблицу films.

films.genre_ids text NOT NULL.. - тут я храню ИД жанра через запятую чтобы при открытии страницы с фильмом можно было запросить название жанров без поиска по таблице genre_connect. Типо это для кэша и в другом месте.

Спасибо за ответы. Как я понял- на мускуле да, такое ппц как ... В принципе так и думал, что вот таким вот запросом придётся. Правда Если юзер захочет прыгнуть сразу в середину каталога- хрен ему... в общем спасибо.
 
кстати вот ещё тема для размышления - денормализация.. суть в следующем.. поскольку речь идёт о фильмах, есть основание полагать, что интересует сортировка по алфавиту и рейтингу.. для примера возьмем второй вариант (с первым действия аналогичны)..
что делаем:

1. создаём поле с индексом - films.order_rating_id (bigint default 0)
2. в некий момент (по крону, по кнопке, иному событию:(
2.1 грохаем индекс (обязательно, иначе долго обновляться будет)
2.2 UPDATE films SET order_rating_id = 0;
2.2 UPDATE films SET order_rating_id = order_rating_id + 1 ORDER BY rating ASC, id;
2.3 считаем count таблицы films (долго и нудно) и куда-нить записываем (в поле рядом, в таблицу конфигов, в файл, etc)
2.4 восстанавливаем индекс
3. соответственно в запросе меняется WHERE order_rating_id > 111 ORDER BY order_rating_id LIMIT 20, общую сумму страниц берем из места, куда записали результат 2.3

в чём профит - упорядоченная последовательность полей, позволяющая делать постраничку для любой точки (поле order_rating_id имеет строгую последовательность).. на ап, полагаю, уйдут секунды.. в чём минус - дополнительные телодвижения; на одной и той же странице с течением времени будут появляться разные записи..

предлагаю попробовать.. самому интересно.. ;)

зы.. кстати можно и дальше пойти - повесить на таблицу можно триггер, который при добавлении/удалении записи сам всё пересчитывать.. по скольку модификация относительно чтения редкая процедура, можно и потерпеть (если, конечно, не тысячами потоком вставляется)..
 
Спасибо за хорошую идею и подробную инструкцию. Думал о таком.
Постоянное изменение таблицы с обновлением результатов меня не пугает. Но, у меня будет сортировки по 5 полям ( не одновременно, цена/популярность/продолжительность... ) =>нужно 5 полей обновлять... ладно, пусть

Но, я никак не возьму в толк как тут с выборкой по определённому жанру. Для просмотра всего каталога - это пойдёт идеально. А для жанра , опять будет JOIN запрос
JOIN genre ON genre_connect.film_id = film.id
WHERE order_rating_id > 111 AND ORDER BY order_rating_id LIMIT 20
, причём высчитанное значение постраничной навигации order_rating_id сдвинет курсор, но из-за того, что не все принадлежат жанру опять будут пропущенные значения=> уже не понятно как высчитывать order_rating_id, только как на хабре - передавать с запросом к следующей странице. Но из-за этого не особо получится сделать навигацию типа 1,2,3,4,5... а только на следующую.
Есть пара бредовых вариантов и ещё один

Делаем 2 таблицы (можно и одну) для каждого типа сортировки (таблицы будут огромные, как бы перемножение множеств)
Первая будет давать нам список ИД фильмов для страницы
id | film_id | genre_id | rating
Заполняем её через запрос select 0, film.id, genre_connect.genre_id, film.rating FROM film JOIN genre ON genre_connect.film_id = film.id ORDER BY genre_connect.genre_id , film.rating
Получится таким образом что каждый genre_id - сдвинут относительно начала на количество новостей в предыдущей категории. Которое можно посчитать.
Недостаток- куча таблиц, причём не маленьких. И ещё больше лишних действий
 
Назад
Сверху