表结构:
CREATE TABLE `mytable` (
`id` varchar(8) NOT NULL,
`event` varchar(32) NOT NULL,
`event_date` date NOT NULL,
`event_time` time NOT NULL,
KEY `id` (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8
此表中的数据如下所示:
id | event | event_date | event_time
---------+------------+-------------+-------------
ref1 | someevent1 | 2010-01-01 | 01:23:45
ref1 | someevent2 | 2010-01-01 | 02:34:54
ref1 | someevent3 | 2010-01-18 | 01:23:45
ref2 | someevent4 | 2012-10-05 | 22:23:21
ref2 | someevent5 | 2012-11-21 | 11:22:33
该表包含大约 500.000.000 条与此类似的记录。
我想在这里询问的查询如下所示:
SELECT *
FROM `mytable`
WHERE `id` = 'ref1'
ORDER BY event_date DESC,
event_time DESC
LIMIT 0, 500
EXPLAIN
输出如下:
select_type: SIMPLE
table: E
type: ref
possible_keys: id
key: id
key_len: 27
ref: const
rows: 17024 (a common example)
Extra: Using where; Using filesort
目的:
此查询由网站生成,LIMIT
值用于页面导航元素,因此如果用户想要查看较旧的条目,它们将调整为 500、500
,然后是 1000、500
等等。
由于id
字段中的一些项可以设置在相当多的行中,行数越来越多当然会导致查询变慢。分析那些缓慢的查询向我展示了排序的原因,在查询期间的大部分时间 mysql 服务器忙于对数据进行排序。索引字段 event_date
和 event_time
并没有太大改变。
示例 SHOW PROFILE
结果,按持续时间排序:
state | duration/sec | percentage
---------------|--------------|-----------
Sorting result | 12.00145 | 99.80640
Sending data | 0.01978 | 0.16449
statistics | 0.00289 | 0.02403
freeing items | 0.00028 | 0.00233
...
Total | 12.02473 | 100.00000
现在问题:
在深入研究像 sort_buffer_size
这样的 mysql 变量之前和其他服务器配置选项,您能否想出任何方法来更改查询或排序行为,以便排序不再是一个大的性能消耗者并且此查询的目的仍然存在?
我不介意有一点跳出框框的想法。
提前致谢!
最佳答案
正如我在评论中所写,多列索引(id、evet_date desc、event_time desc)可能会有所帮助。
如果此表增长很快,您应该考虑在应用程序中添加选项,供用户选择特定日期范围内的数据。
示例:第一步始终返回 500 条记录,但要选择下一条记录,用户应设置数据的日期范围,然后设置分页。
关于大型表中排序查询的 mysql 性能改进,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13308799/