我有一个很大但很窄的InnoDB表,记录大约9米.在桌子上count(*)或count(id)桌子上做的非常慢(6秒以上):
DROP TABLE IF EXISTS `perf2`;
CREATE TABLE `perf2` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`channel_id` int(11) DEFAULT NULL,
`timestamp` bigint(20) NOT NULL,
`value` double NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `ts_uniq` (`channel_id`,`timestamp`),
KEY `IDX_CHANNEL_ID` (`channel_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
RESET QUERY CACHE;
SELECT COUNT(*) FROM perf2;
Run Code Online (Sandbox Code Playgroud)
虽然声明不经常运行,但优化它会很好.根据http://www.cloudspace.com/blog/2009/08/06/fast-mysql-innodb-count-really-fast/,这可以通过强制InnoDB使用索引来实现:
SELECT COUNT(id) FROM perf2 USE INDEX (PRIMARY);
Run Code Online (Sandbox Code Playgroud)
解释计划似乎很好:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE perf2 index NULL PRIMARY 4 NULL 8906459 Using index
Run Code Online (Sandbox Code Playgroud)
不幸的是,声明和以前一样慢.根据"SELECT COUNT(*)"很慢,即使使用where子句,我也尝试优化表而没有成功.
什么/是优化COUNT(*)InnoDB性能的方法?
and*_*dig 17
暂时我通过使用这个近似解决了这个问题:
EXPLAIN SELECT COUNT(id) FROM data USE INDEX (PRIMARY)
Run Code Online (Sandbox Code Playgroud)
rows如上所示,使用InnoDB时,可以从解释计划的列中读取大致的行数.当使用MyISAM时,这将保持EMPTY,因为表格参考正在优化 - 所以如果空回退到传统SELECT COUNT.
Che*_*Che 16
从MySQL 5.1.6开始,您可以使用事件调度程序并定期将计数插入统计表.
首先创建一个表来保存计数:
CREATE TABLE stats (
`key` varchar(50) NOT NULL PRIMARY KEY,
`value` varchar(100) NOT NULL);
Run Code Online (Sandbox Code Playgroud)
然后创建一个事件来更新表:
CREATE EVENT update_stats
ON SCHEDULE
EVERY 5 MINUTE
DO
INSERT INTO stats (`key`, `value`)
VALUES ('data_count', (select count(id) from data))
ON DUPLICATE KEY UPDATE value=VALUES(value);
Run Code Online (Sandbox Code Playgroud)
它并不完美,但它提供了一个独立的解决方案(没有cronjob或队列),可以轻松定制,以便按照计数所需的新鲜度运行.
MQu*_*ion 14
基于@Che代码,您还可以在INSERT和UPDATE上使用触发器来执行perf2,以使stats表中的值保持最新.
CREATE TRIGGER `count_up` AFTER INSERT ON `perf2` FOR EACH ROW UPDATE `stats`
SET
`stats`.`value` = `stats`.`value` + 1
WHERE
`stats`.`key` = "perf2_count";
CREATE TRIGGER `count_down` AFTER DELETE ON `perf2` FOR EACH ROW UPDATE `stats`
SET
`stats`.`value` = `stats`.`value` - 1
WHERE
`stats`.`key` = "perf2_count";
Run Code Online (Sandbox Code Playgroud)
这将具有消除执行计数(*)的性能问题的优点,并且仅在表perf2中的数据改变时执行
| 归档时间: |
|
| 查看次数: |
39937 次 |
| 最近记录: |