Оптимизировать GROUP BY после запроса ранжированного индекса - PullRequest
2 голосов
/ 29 декабря 2010

У меня есть приложение с контентом, которое должно подсчитывать ответы во временном интервале, а затем упорядочивать их по количеству ответов. В настоящее время он отлично работает с небольшим набором данных, но его необходимо масштабировать до миллионов строк. Мой текущий запрос не будет работать.

mysql> describe Responses;
+---------------+---------------------+------+-----+---------+-------+
| Field         | Type                | Null | Key | Default | Extra |
+---------------+---------------------+------+-----+---------+-------+
| site_id       | int(10) unsigned    | NO   | MUL | NULL    |       |
| content_id    | bigint(20) unsigned | NO   | PRI | NULL    |       |
| response_id   | bigint(20) unsigned | NO   | PRI | NULL    |       |
| date          | int(10) unsigned    | NO   |     | NULL    |       |
+---------------+---------------------+------+-----+---------+-------+

Тип таблицы InnoDB, первичный ключ включен (content_id, response_id). Существует дополнительный индекс для (content_id, date), используемый для поиска ответов на фрагмент содержимого, и еще один дополнительный индекс для (site_id, date), используемый в запросе, с которым у меня возникли проблемы:

mysql> explain SELECT content_id id, COUNT(response_id) num_responses
               FROM Responses
               WHERE site_id = 1
                 AND date > 1234567890
                 AND date < 1293579867
               GROUP BY content_id
               ORDER BY num_responses DESC
               LIMIT 0, 10;
+----+-------------+-----------+-------+---------------+------+---------+------+------+-----------------------------------------------------------+
| id | select_type | table     | type  | possible_keys | key  | key_len | ref  | rows | Extra                                                     |
+----+-------------+-----------+-------+---------------+------+---------+------+------+-----------------------------------------------------------+
|  1 | SIMPLE      | Responses | range | date          | date | 8       | NULL |  102 | Using where; Using index; Using temporary; Using filesort |
+----+-------------+-----------+-------+---------------+------+---------+------+------+-----------------------------------------------------------+

Это лучшее, что я смог придумать, но в конечном итоге нужно будет насчитать 1 000 000 строк, что приведет к сортировке 10 000 строк, чтобы набрать горстку результаты.

Я не могу придумать и способ пересчета счета, поскольку диапазон дат произвольный. У меня есть некоторая свобода в изменении первичного ключа: он может состоять из content_id, response_id и site_id в любом порядке, но не может содержать дату.

Приложение разработано в основном на PHP, поэтому, если есть более быстрый способ достичь тех же результатов, разделив запрос на подзапросы, используя временные таблицы или выполняя какие-либо действия на стороне приложения, я открыт для предложений.

Ответы [ 3 ]

1 голос
/ 29 декабря 2010

(перенесено из комментариев по запросу)

Настройка таблицы с тремя столбцами: id, date и num_responses.Столбец num_responses состоит из количества ответов для данного идентификатора на данную дату.Заполните таблицу соответствующим образом, а затем около полуночи (или позже) каждую ночь запускайте скрипт, который добавляет новую строку для предыдущего дня.

Затем, чтобы получить нужные вам строки, вы можете просто запросТаблица, упомянутая выше.

1 голос
/ 29 декабря 2010

Вместо того, чтобы вычислять каждый раз, как насчет кэширования рассчитанного числа с момента последнего запроса и добавления приращения числа для обновления кэша, помещая условие даты в предложение WHERE?

0 голосов
/ 29 декабря 2010

Рассматривали ли вы разбиение таблицы по дате? Есть ли на столе какие-нибудь индексы?

...