Сортировка элементов, отфильтрованных по тегу

0

Я хочу реализовать очень распространенную функцию - фильтрацию некоторых элементов по тегу. В Интернете есть много учебных пособий с примерами того, как это сделать. Запрос довольно прост и быстр (при условии наличия соответствующих индексов).
Но обычно отфильтрованные элементы нужно сортировать по некоторому полю. Например, когда вы фильтруете вопросы по тегу на 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 вызывает filesort. Решение было таким же.

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

  • 0
    это предметы или предмет? путать ... вы можете захотеть перепроверить SQL
  • 0
    Я редактировал SQL, я имел в виду элемент таблицы, конечно
Теги:
tags
join
query-optimization
sql-order-by

2 ответа

1
Лучший ответ

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

  • 0
    Проблема не только в сортировке файлов, но и в создании временной таблицы. Большую часть времени он проводит копирование во временную таблицу. Могу ли я что-нибудь сделать с этим?
  • 0
    Извините, но не. Это ограничение MySQL.
0

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

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

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

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

  • 0
    У нас есть такая проблема: когда вы фильтруете по тегу, вы сначала видите новые вопросы (или самые горячие, это не имеет значения).

Ещё вопросы

Сообщество Overcoder
Наверх
Меню