Сортировка элементов, отфильтрованных по тегу - PullRequest
0 голосов
/ 28 ноября 2010

Я хочу реализовать очень распространенную функцию - фильтрацию некоторых элементов по тегам. В Интернете есть много учебных пособий с примерами того, как это сделать. Запрос довольно простой и быстрый (при условии наличия правильных индексов).
Но обычно отфильтрованные элементы должны быть отсортированы по некоторому полю. Например, когда вы фильтруете вопросы по тегу в SO, результаты сортируются.

Чтобы выполнить эту задачу (при условии, что нам нужно отсортировать по рейтингу), можно написать:

SELECT item.id FROM item
    INNER JOIN taggeditem ON taggeditem.item_id = item.id
WHERE
    taggeditem.tag_id = 1234
ORDER BY item.rating DESC

У нас есть индексы (taggeditem.tag_id), (item.id), (item.rating) Проблема с этим запросом состоит в том, что mysql не может использовать индекс для item.rating, потому что ключ, используемый для выборки строк, не совпадает с ключом, используемым в ORDER BY ( MySQL: ORDER BY Optimization ). Это приводит к использованию временной таблицы и сортировки файлов, что, в свою очередь, приводит к медленному времени выполнения.

Решение, которое я нашел, заключается в денормализации поля сортировки в таблицу taggeditem, чтобы я мог создать индекс (tag_id, item_rating) для taggeditem.

Я искал похожие вопросы в SO и нашел только один: Mysql медленный запрос: INNER JOIN + ORDER BY вызывает сортировку файлов . Решение было таким же.

Итак, я хочу спросить, это общее решение этой проблемы? Является ли хорошей практикой денормализация группы полей сортировки в тегированный элемент, например, созданный, рейтинг? В SO вы можете сортировать, используя 4 различных параметра (самые новые, горячие, голоса, активные) - означает ли это, что они денормализованы поля, которые используются для сортировки результатов? Есть ли альтернативы этому решению?

Ответы [ 2 ]

1 голос
/ 28 ноября 2010

Существует стандартная альтернатива - изменение системных переменных сервера. Например, вы можете поэкспериментировать со значением sort_buffer_size (по умолчанию 2MB). Подробнее об этом.

0 голосов
/ 23 июня 2011

Как только вы используете JOIN и фильтруете объединенную таблицу, вы застреваете с низкой производительностью.

Как вы сказали, единственный способ избежать этого - создать денормализованныйтаблица.

Для сортировок SO, я думаю, у них нет такой проблемы: им просто нужно отсортировать ответы по столбцу таблицы ответов (что-то вроде SELECT * FROM answers WHERE question_id = 1234 SORT BY answer_date, с индексом question_id, answer_date)

Я также ищу такие решения с многозначными столбцами, и это действительно сложно (денормализованные данные будут огромными, так как необходимо пересечь все значения в многозначных столбцах)

...