我正在尝试为表格填充一些数据。该查询正在包含约5000万条记录的表上运行。我目前使用的查询如下。它计算与template
id匹配的行数,并且BETWEEN
两个unix时间戳:
SELECT COUNT(*) as count FROM `s_log`
WHERE `time_sent` BETWEEN '1346904000' AND '1346993271'
AND `template` = '1'
虽然上面的查询确实有效,但在循环遍历每个template
时性能相当慢,有时可能是数百个。时间戳存储为int
并正确编入索引。只是为了测试一下,我尝试运行下面的查询,省略time_sent
限制:
SELECT COUNT(*) as count FROM `s_log`
AND `template` = '1'
正如预期的那样,它运行得非常快,但显然不会在正确的时间范围内限制计数结果。如何获取特定template
的计数并限制该计数BETWEEN
两个unix时间戳?
EXPLAIN:
1 |简单| s_log | ref | time_sent,模板|模板| 4 | const | 71925 |使用何处
SHOW CREATE TABLE s_log:
CREATE TABLE `s_log` (
`id` int(255) NOT NULL AUTO_INCREMENT,
`email` varchar(255) NOT NULL,
`time_sent` int(25) NOT NULL,
`template` int(55) NOT NULL,
`key` varchar(255) NOT NULL,
`node_id` int(55) NOT NULL,
`status` varchar(55) NOT NULL,
PRIMARY KEY (`id`),
KEY `email` (`email`),
KEY `time_sent` (`time_sent`),
KEY `template` (`template`),
KEY `node_id` (`node_id`),
KEY `key` (`key`),
KEY `status` (`status`),
KEY `timestamp` (`timestamp`)
) ENGINE=MyISAM AUTO_INCREMENT=2078966 DEFAULT CHARSET=latin1
答案 0 :(得分:1)
在这种情况下,您可能拥有的最佳索引是复合索引template + time_sent
CREATE INDEX template_time_sent ON s_log (template, time_sent)
PS:同样只要查询中的所有列都是整数 DO NOT 将它们的值括在引号中(在某些情况下,它可能会导致问题,至少在较旧的mysql版本中)< / p>
答案 1 :(得分:0)
首先,您必须创建一个将两个列放在一起的索引(不是单独的)。还要检查你的表类型,我认为如果你的表是innoDB,它会很好用。
最后,以这种方式使用WHERE子句:
`WHERE
模板= '1' AND
time_sent` BETWEEN'1346904000'和'1346993271'
这样做首先检查模板是否为1,如果是,那么它将检查第二个条件否则跳过。这肯定会给你性能优势
答案 2 :(得分:0)
如果您必须为每个模板调用查询,那么使用GROUP BY
通过一次查询调用获取所有信息会更快:
SELECT template, COUNT(*) as count FROM `s_log`
WHERE `time_sent` BETWEEN 1346904000 AND 1346993271;
GROUP BY template
只是猜测这会更快,你也需要重新设计你的代码。
<小时/> 您也可以尝试使用InnoDB
代替MyISAM
。 InnoDB
使用聚簇索引,该索引可能在大型表上执行得更好。来自MySQL网站:
通过聚簇索引访问行很快,因为行数据位于索引搜索所在的同一页面上。如果表很大,与使用与索引记录不同的页面存储行数据的存储组织相比,聚簇索引体系结构通常会保存磁盘I / O操作。 (例如,MyISAM使用一个文件用于数据行,另一个文件用于索引记录。)
Stackoverflow上有一些问题讨论InnoDB
和MyISAM
之间的效果: