MySQL 5.1 到 5.6:巨大的性能冲击

Cha*_*tin 7 mysql innodb myisam mysqldump performance

好吧,这可能是三个问题。我想将使用 MyISAM 的现有 MySQL 5.1 数据库移动到使用 InnoDB 的 5.6,因为我认为有很多明显的 - 甚至可能是好的 - 原因。

这是在 Amazon RDS 上,所以我的升级路线仅限于转储和重新创建数据库。

我会欣然承认我不是一个老练的 DBA。

问题 1:哇这么慢!

大约需要 15 分钟 mysqldump我们的 1.6 亿多行。(表演桌等来了,抱紧你的马。)

花了大约 50 个小时加载到 mysql 5.6 实例中,并且引擎巧妙地将 sed-script-ed 加载到 InnoDB。

问题 2:我的行在哪里?

select count(*) from node;在目前的 DB 上给出了大约 1.62 亿。在5.6上,它给出了大约9300万。加载似乎是成功的,尽管我无法证明;至少,加载终止后没有错误消息。

如果它不成功,那真的慢。

问题 3:这么慢!

因此,select count(*) from node;在 5.1 上几乎没有任何时间完成——查询结果在 0.00 到 0.03 秒之间。在使用 InnoDB 的 5.6 上,这需要一分钟多的时间。解释清楚地表明这是因为查询优化的方式不同——但不清楚为什么不同。

表格和说明

MySQL 5.1

mysql> show create table node\G
*************************** 1. row ***************************
       Table: node
Create Table: CREATE TABLE `node` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `graph` varchar(100) CHARACTER SET latin1 DEFAULT NULL,
  `subject` varchar(200) NOT NULL,
  `predicate` varchar(200) NOT NULL,
  `object` mediumtext NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `nodeindex` (`graph`(20),`subject`(100),`predicate`(100),`object`(100)),
  KEY `ix_node_subject` (`subject`),
  KEY `ix_node_graph` (`graph`),
  KEY `ix_node_object` (`object`(255)),
  KEY `ix_node_predicate` (`predicate`),
  KEY `node_po` (`predicate`,`object`(130)),
  KEY `node_so` (`subject`,`object`(130)),
  KEY `node_sp` (`subject`,`predicate`(130)),
  FULLTEXT KEY `node_search` (`object`)
) ENGINE=MyISAM AUTO_INCREMENT=550671861 DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

mysql> select count(id) from node;
+-----------+
| count(id) |
+-----------+
| 163426434 |
+-----------+
1 row in set (0.00 sec)


mysql> explain select count(id) from node;
+----+-------------+-------+------+---------------+------+---------+------+------+------------------------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra                        |
+----+-------------+-------+------+---------------+------+---------+------+------+------------------------------+
|  1 | SIMPLE      | NULL  | NULL | NULL          | NULL | NULL    | NULL | NULL | Select tables optimized away |
+----+-------------+-------+------+---------------+------+---------+------+------+------------------------------+
1 row in set (0.00 sec)
Run Code Online (Sandbox Code Playgroud)

MySQL 5.6

mysql> show create table node\G
*************************** 1. row ***************************
       Table: node
Create Table: CREATE TABLE `node` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `graph` varchar(100) CHARACTER SET latin1 DEFAULT NULL,
  `subject` varchar(200) NOT NULL,
  `predicate` varchar(200) NOT NULL,
  `object` mediumtext NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `nodeindex` (`graph`(20),`subject`(100),`predicate`(100),`object`(100)),
  KEY `ix_node_subject` (`subject`),
  KEY `ix_node_graph` (`graph`),
  KEY `ix_node_object` (`object`(255)),
  KEY `ix_node_predicate` (`predicate`),
  KEY `node_po` (`predicate`,`object`(130)),
  KEY `node_so` (`subject`,`object`(130)),
  KEY `node_sp` (`subject`,`predicate`(130)),
  FULLTEXT KEY `node_search` (`object`)
) ENGINE=InnoDB AUTO_INCREMENT=481239575 DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
Run Code Online (Sandbox Code Playgroud)

``

mysql> explain select count(id) from node;
+----+-------------+-------+-------+---------------+---------------+---------+------+----------+-------------+
| id | select_type | table | type  | possible_keys | key           | key_len | ref  | rows     | Extra       |
+----+-------------+-------+-------+---------------+---------------+---------+------+----------+-------------+
|  1 | SIMPLE      | node  | index | NULL          | ix_node_graph | 103     | NULL | 79671827 | Using index |
+----+-------------+-------+-------+---------------+---------------+---------+------+----------+-------------+
1 row in set (0.00 sec)
Run Code Online (Sandbox Code Playgroud)

Rol*_*DBA 8

您的问题与 MySQL 版本无关。它与存储引擎有关。

问题#1 的答案:哇这么慢!

运行 mysqldump 只涉及来自 .MYDMyISAM 表文件的。因此,我认为在 15 分钟内转储 1.63 亿行并不奇怪。

将数据加载到 Amazon RDS 需要 50 个小时,这对我来说也不令人震惊。为什么 ?

无论您为 MySQL RDS 选择哪种服务器模型,InnoDB 事务日志(ib_logfile0、ib_logfile1)始终为 128M,并且不允许更改,甚至RDS CLI也不行。我之前写过这个:本地数据库 vs 亚马逊 RDS

所有对 InnoDB 的写入都写入双写缓冲区>您应该在加载之前禁用它:请参阅我的帖子加速 InnoDB 插入和更新的可能性

来自每个 INSERT 的每个行块都作为一个事务处理,其中的内容通过 ibdata1 的双写缓冲区和事务日志写入。因此,缓慢。

问题#2 的答案:我的行在哪里?

看看nodeindex. 我可以看到它是一个前缀索引。

根据MySQL 文档CREATE INDEX

前缀支持和前缀长度(如果支持)取决于存储引擎。例如,MyISAM 表的前缀最长可达 1000 字节,InnoDB 表的前缀最长可达 767 字节。

我几乎可以保证长度graph,subject,predicate,object超过 767 的任何行都不会进入 InnoDB 表。

问题 3 的答案:哇这么慢!

这是由于存储引擎。

当你select count(id) from node;对抗 MyISAM 时,MyISAM 会作弊并进入.MYD标题以获取行数。因此,获取行数的运行时间不是实际行数的函数。这就是 MySQL 查询优化器优化所有标准机制并为您提供行计数的方式。

说到 InnoDB,因为它不存储行数,所以每次都必须完全扫描一个表:请参阅我的帖子为什么 InnoDB 不存储行数?

建议

我不会将它导入为 InnoDB。我会先导入 MyISAM。然后,将所有 MyISAM 表转换为 InnoDB。在转换它之前,您可能必须更改nodeindex或完全摆脱它。否则,您将在转换时丢失行。

看我的帖子哪个先:升级mysql版本还是转换存储引擎?想要查询更多的信息。