mysql: оптимизация запроса со смешанным вознесением ORDER BY - PullRequest
2 голосов
/ 04 марта 2010

У меня есть большая таблица (~ 1M строк сейчас, скоро ~ 10M), которая имеет два ранжированных столбца (в дополнение к обычным данным):

  • avg_visited, число с плавающей точкой 0-1, представляющее% возрастной популярности; выше, тем лучше
  • alexa_rank, целое число 1-N, дающее априорный рейтинг

Априорный рейтинг взят из внешних источников, поэтому не может быть изменен. Многие строки еще не пользуются популярностью (так как ни один пользователь еще не нажал на них), поэтому априорное ранжирование - это резервный порядок. Однако популярность меняется очень часто - как для обновления старых записей, так и для добавления популярности к тем, у которых ранее был только априорный рейтинг, если какой-то пользователь действительно ударил его.

Я часто запускаю SELECT id, url, alexa_rank, avg_visited FROM сайтов ORDER BY avg_visited desc, alexa_rank asc LIMIT 49500, 500 (для различных значений 49500).

Однако ORDER BY не может использовать индекс со смешанным возрастанием для http://dev.mysql.com/doc/refman/5.0/en/order-by-optimization.html

Это в MySQL 5.1, innodb.

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

Ответы [ 2 ]

1 голос
/ 04 марта 2010

Просто простой взлом:

Поскольку популярность - это число с плавающей точкой от 0 до 1. Вы можете умножить ее на -1 и число будет от -1 до 0.

Таким образом, вы можете изменить порядок сортировки популярности на ORDER BY popularity ASC, a_priori ASC

Не уверен, что накладные расходы весят усиление.

Это напоминает мне о взломе хранения писем в обратной форме.

1 голос
/ 04 марта 2010

К сожалению, MySQL не поддерживает предложения DESC в индексах и не поддерживает индексы для производных выражений.

Вы можете хранить отрицательную популярность вместе с положительной и использовать ее вORDER BY:

CREATE INDEX ix_mytable_negpopularity_apriori ON (neg_popularity, a_priori);

INSERT
INTO    mytable (popularity, neg_popularity)
VALUES  (@popularity, -@popularity);

SELECT  *
FROM    mytable
ORDER BY
        neg_popularity, a_priori
...