我有一个内容应用程序需要计算时间片中的响应,然后按响应数量排序。它目前适用于小型数据集,但需要扩展到数百万行。我当前的查询无效。
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,主键是on(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开发的,所以如果有更快的方法通过将查询分成子查询,使用临时表或在应用程序端做事来完成相同的结果,我愿意接受建议。 / p>
答案 0 :(得分:1)
不是每次计算,如何缓存自上次查询以来计算的计数,并添加计数增量以通过将日期条件放入WHERE子句来更新缓存?
答案 1 :(得分:1)
(根据要求转发自评论)
设置一个包含三列的表:id,date和num_responses。列num_responses包含给定日期的给定id的响应数。适当地回填表格,然后在每晚午夜(或晚上)左右,运行一个脚本,为前一天添加新行。
然后,要获取所需的行,您只需查询上面提到的表。
答案 2 :(得分:0)
您是否考虑过按日期对表格进行分区?桌子上有指数吗?