0

我正在尝试为表格填充一些数据。该查询正在包含约 5000 万条记录的表上运行。我目前使用的查询如下。它计算匹配templateid 并且是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 | 参考 | time_sent,模板 | 模板 | 4 | 常量 | 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
4

3 回答 3

1

在这种情况下,您可能拥有的最佳索引是复合索引template + time_sent

CREATE INDEX template_time_sent ON s_log (template, time_sent)

PS:只要查询中的所有列都是整数,不要将它们的值括在引号中(在某些情况下,它可能会导致问题,至少对于较旧的 mysql 版本)

于 2012-09-07T05:22:37.103 回答
0

首先,您必须创建一个将两列放在一起(而不是分开)的索引。还要检查你的表类型,如果你的表是 innoDB,我认为它会很好用。

最后,以这种方式使用您的 WHERE 子句:

`WHERE模板= '1' ANDtime_sent` 在 '1346904000' 和 '1346993271' 之间

这样做是首先检查模板是否为 1,如果是则它将检查第二个条件,否则跳过。这肯定会给您带来性能优势

于 2012-09-07T06:23:06.890 回答
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

于 2012-09-07T06:40:47.630 回答