即使使用where子句,“ SELECT COUNT(*)”也很慢
我试图弄清楚如何在MySQL中优化一个非常慢的查询(我没有设计这个):
SELECT COUNT(*) FROM change_event me WHERE change_event_id > '1212281603783391';+----------+
| COUNT(*) |
+----------+
| 3224022 |
+----------+
1 row in set (1 min 0.16 sec)
比较一下:
select count(*) from change_event;+----------+
| count(*) |
+----------+
| 6069102 |
+----------+
1 row in set (4.21 sec)
说明语句对我没有帮助:
explain SELECT COUNT(*) FROM change_event me WHERE change_event_id > '1212281603783391'\G*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: me
type: range
possible_keys: PRIMARY
key: PRIMARY
key_len: 8
ref: NULL
rows: 4120213
Extra: Using where; Using index
1 row in set (0.00 sec)
好的,它仍然认为它需要大约400万个条目才能计数,但是我可以计算文件中的行数比这还要快!我不明白为什么MySQL要花这么长时间。
这是表的定义:
CREATE TABLE `change_event` ( `change_event_id` bigint(20) NOT NULL default '0',
`timestamp` datetime NOT NULL,
`change_type` enum('create','update','delete','noop') default NULL,
`changed_object_type` enum('Brand','Broadcast','Episode','OnDemand') NOT NULL,
`changed_object_id` varchar(255) default NULL,
`changed_object_modified` datetime NOT NULL default '1000-01-01 00:00:00',
`modified` datetime NOT NULL default '1000-01-01 00:00:00',
`created` datetime NOT NULL default '1000-01-01 00:00:00',
`pid` char(15) default NULL,
`episode_pid` char(15) default NULL,
`import_id` int(11) NOT NULL,
`status` enum('success','failure') NOT NULL,
`xml_diff` text,
`node_digest` char(32) default NULL,
PRIMARY KEY (`change_event_id`),
KEY `idx_change_events_changed_object_id` (`changed_object_id`),
KEY `idx_change_events_episode_pid` (`episode_pid`),
KEY `fk_import_id` (`import_id`),
KEY `idx_change_event_timestamp_ce_id` (`timestamp`,`change_event_id`),
KEY `idx_change_event_status` (`status`),
CONSTRAINT `fk_change_event_import` FOREIGN KEY (`import_id`) REFERENCES `import` (`import_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
版:
$ mysql --versionmysql Ver 14.12 Distrib 5.0.37, for pc-solaris2.8 (i386) using readline 5.0
有什么明显的我想念的东西吗?(是的,我已经尝试过“ SELECT COUNT(change_event_id)”,但是没有性能差异)。
回答:
InnoDB使用集群主键,因此主键与行一起存储在数据页中,而不是存储在单独的索引页中。为了进行范围扫描,您仍然必须扫描数据页中所有可能较宽的行。请注意,此表包含一个TEXT列。
我会尝试两件事:
- 运行
optimize table
。这将确保数据页按排序顺序进行物理存储。可以想象,这可以加快对群集主键的范围扫描。 - 仅在change_event_id列上创建一个附加的非主索引。这会将该列的副本存储在索引页面中,从而使扫描速度更快。创建它之后,检查说明计划以确保它正在使用新索引。
(如果从零开始递增,您可能还想使change_event_id列bigint 无符号 )
以上是 即使使用where子句,“ SELECT COUNT(*)”也很慢 的全部内容, 来源链接: utcz.com/qa/404557.html