我正试图找出如何在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 --version
mysql  Ver 14.12 Distrib 5.0.37, for pc-solaris2.8 (i386) using readline 5.0

我有什么明显的遗漏吗?(是的,我已经try 过" Select 计数(更改事件id)",但没有性能差异).

推荐答案

InnoDB使用集群主键,因此主键与行一起存储在数据页中,而不是单独的索引页中.为了进行范围扫描,您仍然必须扫描数据页中所有可能较宽的行;请注意,此表包含一个文本列.

我会try 两件事:

  1. optimize table.这将确保数据页按排序顺序进行物理存储.这可以提高集群主键的范围扫描速度.
  2. 仅在change_event_id列上创建一个附加的非主索引.这将在索引页中存储该列的副本,这样扫描速度会快得多.创建后,判断解释计划以确保它使用了新索引.

(如果change_event_id列从零开始递增,则可能还希望将其设置为bigint unsigned)

Mysql相关问答推荐

如何使RST(*)在巨大的数据集上快速执行?

对象NotExecutabletry 在远程SQL服务器上执行SQL时出错,并使用SQLAchemy.Create_engine

创建从表中筛选数据的过程时出错

如何在Sequelize中将查询作为选项?

递归查询意外地为一个字段返回空值

查询具有JSON对象数组的列时,JSON_CONTAINS的MySQL语法错误

在 .NET 6 中使用 Dapper Framework 未能成功连接到 MySql

按特定顺序匹配 EventS 和下一个 EventA 之前的第一个 Event 之间的记录

数据导入和默认目标架构空列表. (Mysql 工作台 8)

在 MySQL 中,如何对 LIKE 查询进行批量更新,删除字符?

使用 autocommit = 0 和 InnoDB 表的 LOCK TABLES 检测死锁

如何使用sql查询在日期列中按值和最大值分组的表中添加列?

最后一个字母 '%n' 的 mysql SELECT 字符串不起作用

使用带有 ELSEIF 和 ELSE 的 3 列更新问题

如何将表的链接列转换为 SQL 中的行?

Laravel $q->where() 日期之间

MySQL使用多列 Select 重复记录

在另一个 where 语句(子查询?)中使用一个 sql 查询的结果

如何使用 XML_LOAD() 将 XML 文件导入 MySQL 数据库表;功能

AWS RDS 实例升级停机时间