2010-11-28 2 views
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 не может используйте индекс index.rating, потому что ключ, используемый для извлечения строк, не совпадает с ключом, используемым в ORDER BY (MySQL: ORDER BY Optimization). Это приводит к использованию временной таблицы и filesort, что, в свою очередь, приводит к медленному времени выполнения.

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

Я искал аналогичные вопросы в SO, и нашел только этот: Mysql slow query: INNER JOIN + ORDER BY causes filesort. Решение было таким же.

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

+0

это товар или изделие? путайте ... вам может потребоваться повторная проверка SQL – ajreal 2010-11-28 22:09:05

+0

Я отредактировал SQL, я имел в виду элемент таблицы, конечно, – 2010-11-29 05:34:27

ответ

1

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

+0

Проблема заключается не только в filesort, но и в создании временной таблицы. Большую часть времени он проводит копирование на временную таблицу. Могу ли я что-нибудь с этим сделать? – 2010-11-28 21:59:50

0

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

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

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

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

Смежные вопросы