我有一个约3000万行(并且还在增长!)的表格,目前我在一个简单的范围选择方面遇到了一些问题。
查询,如下所示:
SELECT SUM( CEIL( dlvSize / 100 ) ) as numItems
FROM log
WHERE timeLogged BETWEEN 1000000 AND 2000000
AND user = 'example'</pre>
完成需要几分钟,我认为解决方案将在我正在使用的索引处。以下是解释结果:
+----+-------------+-------+-------+---------------------------------+---------+---------+------+----------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+---------------------------------+---------+---------+------+----------+-------------+
| 1 | SIMPLE | log | range | PRIMARY,timeLogged | PRIMARY | 4 | NULL | 11839754 | Using where |
+----+-------------+-------+-------+---------------------------------+---------+---------+------+----------+-------------+
我的表结构就是这个(减少使其更适合问题):
CREATE TABLE IF NOT EXISTS `log` (
`origDomain` varchar(64) NOT NULL default '0',
`timeLogged` int(11) NOT NULL default '0',
`orig` varchar(128) NOT NULL default '',
`rcpt` varchar(128) NOT NULL default '',
`dlvSize` varchar(255) default NULL,
`user` varchar(255) default NULL,
PRIMARY KEY (`timeLogged`,`orig`,`rcpt`),
KEY `timeLogged` (`timeLogged`),
KEY `orig` (`orig`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
我可以做些什么来优化我的桌面上的查询或索引?
答案 0 :(得分:3)
您可以尝试在(user, timeLogged)
上添加composite index:
CREATE TABLE IF NOT EXISTS `log` (
...
KEY `user_timeLogged` (user, timeLogged),
...
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
相关Stack Overflow帖子:
答案 1 :(得分:1)
除了其他答案提出的建议外,我还注意到表格中有一列user
是varchar(255)
。如果这引用了用户表中的列,则1)最有可能将整数ID列添加到该表中,并将其用作主键和其他表中的引用列; 2)您正在使用InnoDB,那么为什么不利用它提供的外键功能呢?
如果您按varchar(n)
列进行索引,则会将其视为索引中的char(n)
,因此当前主键的每一行占用4 + 128 + 128 = 260字节索引。
答案 2 :(得分:0)
在user
上添加索引。