为大小超过 2GB 的 table 调整 SQL 查询
Tuning SQL Query for a table with size more than 2GB
我有一个包含数百万条记录的 table,table 的大小目前为 2GB,预计会进一步增长
Table结构
CREATE TABLE `test` (
`column_1` int(11) NOT NULL AUTO_INCREMENT,
`column_2` int(11) NOT NULL,
`column_3` int(11) NOT NULL,
`column_4` int(11) NOT NULL,
`column_5` datetime NOT NULL,
`column_6` time NOT NULL,
PRIMARY KEY (`column_1`),
UNIQUE KEY `index_1` (`column_2`,`column_3`),
UNIQUE KEY `index_2` (`column_2`,`column_4`),
KEY `index_3` (`column_3`),
KEY `index_4` (`column_4`),
KEY `index_5` (`column_2`),
KEY `index_6` (`column_5`,`column_2`),
CONSTRAINT `fk_1` FOREIGN KEY (`column_3`) REFERENCES `test2`(`id`),
CONSTRAINT `fk_2` FOREIGN KEY (`column_4`) REFERENCES `test2` (`id`),
CONSTRAINT `fl_3` FOREIGN KEY (`column_2`) REFERENCES `link` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=14164023 DEFAULT CHARSET=utf8;
当我 运行 以下查询时,对于 column_2 的不同值大约需要 5-8 秒。有人可以帮助更好地执行此操作吗?
SELECT count(*) FROM test WHERE test.column_2= 26 and
test.column_5 between '2015-06-01 00:00:00' AND
'2015-06-30 00:00:00' ;
注意:提到的时间是通过在 mysql 工作台
上执行查询捕获的
您的 index_6
当前有 column_5
,然后是 column_2
,因此 MySQL 首先尝试根据 BETWEEN
子句进行过滤。然而 MySQL 有限制,在 range 模式下使用索引后,它不能使用索引的第二部分(更多信息在这个 blog post)。 =19=]
优化此类查询的正确方法是将 equation 列作为索引的第一部分,将 range 列作为第二部分。然后 MySQL 将选择 column_2
值为 26
的行,然后将使用索引的第二部分根据 column_5
日期范围进一步过滤它们。
所以解决方案是有一个索引:
KEY `ind_c2_c5` (`column_2`,`column_5`)
顺便说一句,最好给索引起一个描述性的名字,这样你一眼就知道它们的用途...
我有一个包含数百万条记录的 table,table 的大小目前为 2GB,预计会进一步增长
Table结构
CREATE TABLE `test` (
`column_1` int(11) NOT NULL AUTO_INCREMENT,
`column_2` int(11) NOT NULL,
`column_3` int(11) NOT NULL,
`column_4` int(11) NOT NULL,
`column_5` datetime NOT NULL,
`column_6` time NOT NULL,
PRIMARY KEY (`column_1`),
UNIQUE KEY `index_1` (`column_2`,`column_3`),
UNIQUE KEY `index_2` (`column_2`,`column_4`),
KEY `index_3` (`column_3`),
KEY `index_4` (`column_4`),
KEY `index_5` (`column_2`),
KEY `index_6` (`column_5`,`column_2`),
CONSTRAINT `fk_1` FOREIGN KEY (`column_3`) REFERENCES `test2`(`id`),
CONSTRAINT `fk_2` FOREIGN KEY (`column_4`) REFERENCES `test2` (`id`),
CONSTRAINT `fl_3` FOREIGN KEY (`column_2`) REFERENCES `link` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=14164023 DEFAULT CHARSET=utf8;
当我 运行 以下查询时,对于 column_2 的不同值大约需要 5-8 秒。有人可以帮助更好地执行此操作吗?
SELECT count(*) FROM test WHERE test.column_2= 26 and
test.column_5 between '2015-06-01 00:00:00' AND
'2015-06-30 00:00:00' ;
注意:提到的时间是通过在 mysql 工作台
上执行查询捕获的您的 index_6
当前有 column_5
,然后是 column_2
,因此 MySQL 首先尝试根据 BETWEEN
子句进行过滤。然而 MySQL 有限制,在 range 模式下使用索引后,它不能使用索引的第二部分(更多信息在这个 blog post)。 =19=]
优化此类查询的正确方法是将 equation 列作为索引的第一部分,将 range 列作为第二部分。然后 MySQL 将选择 column_2
值为 26
的行,然后将使用索引的第二部分根据 column_5
日期范围进一步过滤它们。
所以解决方案是有一个索引:
KEY `ind_c2_c5` (`column_2`,`column_5`)
顺便说一句,最好给索引起一个描述性的名字,这样你一眼就知道它们的用途...