【发布时间】:2010-12-30 00:47:11
【问题描述】:
我有一个内容应用程序,它需要在一个时间片内计算响应,然后按响应数对它们进行排序。它目前适用于小型数据集,但需要扩展到数百万行。我当前的查询不起作用。
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 开发,因此如果有更快的方法通过将查询拆分为子查询、使用临时表或在应用程序端执行操作来完成相同的结果,我愿意接受建议。
【问题讨论】:
-
也许你可以尝试索引
site_id, date plus content_id? -
在 InnoDB 中,二级索引通过指向主键来工作(然后使用主键检索结果)。这样做的副作用是所有辅助键本质上都在末尾附加了主键列。因此索引 (site_id, date) 的行为类似于 (site_id, date, content_id, response_id)。
标签: sql mysql optimization group-by