【发布时间】:2011-05-18 18:38:14
【问题描述】:
我有一个使用 InnoDB 的表来存储我的系统发送的所有消息。目前该表有 4000 万行,并且每月增长 3/4 百万。
我的查询基本上是选择从用户和数据范围内发送的消息。这是一个简单的创建表:
创建表 `log` ( `id` int(10) NOT NULL DEFAULT '0', `type` varchar(10) NOT NULL DEFAULT '', `timeLogged` int(11) NOT NULL DEFAULT '0', `orig` varchar(128) NOT NULL DEFAULT '', `rcpt` varchar(128) NOT NULL DEFAULT '', `user` int(10) 默认为空, 主键(`id`), KEY `timeLogged`(`timeLogged`), KEY `user` (`user`), KEY `user_timeLogged` (`user`,`timeLogged`) ) ENGINE=InnoDB 默认字符集=latin1;
注意:由于其他查询,我也有单独的索引。
查询如下所示:
SELECT COUNT(*) FROM log WHERE timeLogged BETWEEN 1282878000 AND 1382878000 AND user = 20
问题在于,此查询需要 2 分钟到 10 分钟,具体取决于用户和服务器负载,等待页面加载的时间太长。我启用了mysql缓存并在应用程序中缓存,但问题是当用户搜索新范围时,它不会命中缓存。
我的问题是:
- 更改 user_timeLogged 索引会有什么不同吗?
- 这是 MySQL 和大型数据库的问题吗?我的意思是,Oracle 或其他数据库是否也会遇到这个问题?
AFAIK,我的索引已正确创建,此查询不应该花这么长时间。
感谢任何帮助的人!
【问题讨论】:
-
发布来自以下
EXPLAIN SELECT COUNT(*) FROM log WHERE timeLogged BETWEEN 1282878000 AND 1382878000 AND user = 20;的输出 -
我会将此作为评论发布,因为它不涉及查询优化,但您是否考虑过归档策略而不是将所有消息保存在一个表中?以 750k/月的速度记录 4000 万条记录意味着超过四年的数据价值。除非确实以相同频率查询任意年龄的消息,否则您可能需要考虑将旧消息移动到单独的表,并实现将旧消息请求定向到该表的逻辑。
-
查询中没有太多需要优化的地方。你的 key_buffer 有多大?
-
你的意思是
innodb_buffer_pool_size,因为它是 InnoDB 表。