【问题标题】:AWS RDS performance is very very lowAWS RDS 性能非常非常低
【发布时间】:2020-06-01 15:08:05
【问题描述】:

有两个数据库,AWS RDS 和 Digitalocean $5 VPS。 我将相同的 .sql 文件导入到两个数据库中,它们之间的性能差异几乎是 66000%

select count(special_cargo_id) from special_cargos;

AWS RDS 运行时间 = 35.681 秒

在 Mysql 上执行 5$ VPS 耗时 = 0.086 秒

详情:

表格长度

1.85GB 行 ~260k

MySQL 版本 8

表引擎 InnoDB

RDS 输出

CREATE TABLE `special_cargos` (
  `special_cargo_id` int(11) NOT NULL AUTO_INCREMENT,
  `barcode` varchar(20) DEFAULT '',
  `salesCode` varchar(15) NOT NULL,
  `price` varchar(15) NOT NULL,
  `para` varchar(3) DEFAULT NULL,
  `postaceki` varchar(25) DEFAULT '',
  `iban` varchar(30) DEFAULT NULL,
  `send_type` tinyint(1) unsigned NOT NULL,
  `customer_id` int(11) NOT NULL,
  `address_id` int(11) NOT NULL,
  `height` varchar(5) DEFAULT '',
  `weight` varchar(5) DEFAULT '',
  `width` varchar(5) NOT NULL DEFAULT '',
  `desi` varchar(5) DEFAULT '',
  `length` varchar(255) DEFAULT '',
  `customer_firstname` varchar(32) NOT NULL,
  `customer_lastname` varchar(32) NOT NULL,
  `customer_company` varchar(40) NOT NULL,
  `customer_address` varchar(255) NOT NULL,
  `customer_city` int(11) NOT NULL DEFAULT '0',
  `customer_city_name` varchar(55) DEFAULT '',
  `customer_zone_id` int(11) NOT NULL DEFAULT '0',
  `customer_zone_name` varchar(55) DEFAULT '',
  `customer_postcode` varchar(10) NOT NULL,
  `firstname` varchar(32) NOT NULL,
  `lastname` varchar(32) NOT NULL,
  `company` varchar(40) DEFAULT '',
  `address` varchar(255) NOT NULL,
  `country_id` int(5) DEFAULT NULL,
  `country_name` varchar(64) DEFAULT NULL,
  `city_id` int(11) NOT NULL,
  `city_name` varchar(55) NOT NULL,
  `district_id` int(11) NOT NULL,
  `district_name` varchar(64) NOT NULL,
  `email` varchar(96) NOT NULL,
  `phone` varchar(55) NOT NULL,
  `postcode` varchar(10) DEFAULT '',
  `product` text,
  `sendText` text,
  `returnText` text,
  `created_at` datetime DEFAULT NULL,
  `updated_at` datetime DEFAULT NULL,
  `deleted_at` datetime DEFAULT NULL,
  `cargo_firm` tinyint(1) NOT NULL DEFAULT '0',
  `ups_barcode_link` text,
  `status` tinyint(1) NOT NULL DEFAULT '0',
  PRIMARY KEY (`special_cargo_id`),
  KEY `customer_id` (`customer_id`),
  KEY `special_cargo_id` (`special_cargo_id`),
  KEY `barcode` (`barcode`),
  KEY `salesCode` (`salesCode`),
  KEY `price` (`price`),
  KEY `postaceki` (`postaceki`),
  KEY `customer_firstname` (`customer_firstname`),
  KEY `customer_lastname` (`customer_lastname`),
  KEY `firstname` (`firstname`),
  KEY `lastname` (`lastname`),
  KEY `customer_company` (`customer_company`),
  KEY `customer_address` (`customer_address`),
  KEY `customer_city_name` (`customer_city_name`),
  KEY `customer_zone_name` (`customer_zone_name`),
  KEY `company` (`company`),
  KEY `address` (`address`),
  KEY `city_name` (`city_name`),
  KEY `district_name` (`district_name`),
  KEY `email` (`email`),
  KEY `phone` (`phone`),
  KEY `postcode` (`postcode`),
  KEY `index_special_cargos` (`special_cargo_id`)
) ENGINE=InnoDB AUTO_INCREMENT=497539 DEFAULT CHARSET=utf8

+-----------------------+----------+
|Variable_name          |Value     |
+-----------------------+----------+
|innodb_buffer_pool_size|1073741824|
+-----------------------+----------+

+--+-----------+--------------+----------+-----+-------------+-----------+-------+----+------+--------+-----------+
|id|select_type|table         |partitions|type |possible_keys|key        |key_len|ref |rows  |filtered|Extra      |
+--+-----------+--------------+----------+-----+-------------+-----------+-------+----+------+--------+-----------+
|1 |SIMPLE     |special_cargos|NULL      |index|NULL         |customer_id|4      |NULL|146973|100     |Using index|
+--+-----------+--------------+----------+-----+-------------+-----------+-------+----+------+--------+-----------+

MYSQL 输出上的简单 VPS

CREATE TABLE `special_cargos` (
  `special_cargo_id` int(11) NOT NULL AUTO_INCREMENT,
  `barcode` varchar(20) NOT NULL,
  `salesCode` varchar(15) NOT NULL,
  `price` varchar(15) NOT NULL,
  `para` varchar(3) DEFAULT NULL,
  `postaceki` varchar(25) NOT NULL,
  `iban` varchar(30) DEFAULT NULL,
  `send_type` tinyint(1) unsigned NOT NULL,
  `customer_id` int(11) NOT NULL,
  `address_id` int(11) NOT NULL,
  `height` varchar(5) NOT NULL,
  `weight` varchar(5) NOT NULL,
  `width` varchar(5) NOT NULL,
  `desi` varchar(5) NOT NULL,
  `length` varchar(255) NOT NULL,
  `customer_firstname` varchar(32) NOT NULL,
  `customer_lastname` varchar(32) NOT NULL,
  `customer_company` varchar(40) NOT NULL,
  `customer_address` varchar(255) NOT NULL,
  `customer_city` int(11) NOT NULL,
  `customer_city_name` varchar(55) NOT NULL,
  `customer_zone_id` int(11) NOT NULL,
  `customer_zone_name` varchar(55) NOT NULL,
  `customer_postcode` varchar(10) NOT NULL,
  `firstname` varchar(32) NOT NULL,
  `lastname` varchar(32) NOT NULL,
  `company` varchar(40) NOT NULL,
  `address` varchar(255) NOT NULL,
  `country_id` int(5) DEFAULT NULL,
  `country_name` varchar(64) DEFAULT NULL,
  `city_id` int(11) NOT NULL,
  `city_name` varchar(55) NOT NULL,
  `district_id` int(11) NOT NULL,
  `district_name` varchar(64) NOT NULL,
  `email` varchar(96) NOT NULL,
  `phone` varchar(55) NOT NULL,
  `postcode` varchar(10) NOT NULL,
  `product` text,
  `sendText` text NOT NULL,
  `returnText` text NOT NULL,
  `created_at` datetime NOT NULL,
  `updated_at` datetime NOT NULL,
  `deleted_at` datetime DEFAULT NULL,
  `cargo_firm` int(1) NOT NULL DEFAULT '0',
  `ups_barcode_link` text,
  `status` int(1) NOT NULL DEFAULT '0',
  PRIMARY KEY (`special_cargo_id`),
  KEY `customer_id` (`customer_id`),
  KEY `special_cargo_id` (`special_cargo_id`),
  KEY `barcode` (`barcode`),
  KEY `salesCode` (`salesCode`),
  KEY `price` (`price`),
  KEY `postaceki` (`postaceki`),
  KEY `customer_firstname` (`customer_firstname`),
  KEY `customer_lastname` (`customer_lastname`),
  KEY `firstname` (`firstname`),
  KEY `lastname` (`lastname`),
  KEY `customer_company` (`customer_company`),
  KEY `customer_address` (`customer_address`),
  KEY `customer_city_name` (`customer_city_name`),
  KEY `customer_zone_name` (`customer_zone_name`),
  KEY `company` (`company`),
  KEY `address` (`address`),
  KEY `city_name` (`city_name`),
  KEY `district_name` (`district_name`),
  KEY `email` (`email`),
  KEY `phone` (`phone`),
  KEY `postcode` (`postcode`)
) ENGINE=InnoDB AUTO_INCREMENT=497037 DEFAULT CHARSET=utf8

+-----------------------+---------+
|Variable_name          |Value    |
+-----------------------+---------+
|innodb_buffer_pool_size|134217728|
+-----------------------+---------+

+--+-----------+--------------+----------+-----+-------------+-----------+-------+----+------+--------+-----------+
|id|select_type|table         |partitions|type |possible_keys|key        |key_len|ref |rows  |filtered|Extra      |
+--+-----------+--------------+----------+-----+-------------+-----------+-------+----+------+--------+-----------+
|1 |SIMPLE     |special_cargos|NULL      |index|NULL         |customer_id|4      |NULL|133967|100     |Using index|
+--+-----------+--------------+----------+-----+-------------+-----------+-------+----+------+--------+-----------+

【问题讨论】:

  • 您好,您能提供更多关于这些规格的详细信息吗?
  • 您好,它们都有 2GB 的 RAM 和 2vCPU,我认为它们之间没有 60000% 的差异
  • 嗨,RDS 的实例类型?
  • 您是否忘记在 RDS 数据库上创建索引?
  • 您好,您可以在导入时检查 BurstBalance 值吗?

标签: mysql amazon-web-services innodb amazon-rds aws-rds-data-service


【解决方案1】:

这里有两个方面的问题。 IMO 的一个和更重要的方面是查询 - 这很糟糕。它进行全索引扫描(是的,PRIMARY 也是一个索引)。它的性能与更好的线性比例呈线性关系,并且需要 B+tree 的 nlog(n)。

第二方面。为什么执行时间不同。它可能与缓存有关(在 DO 的情况下,查询是从缓冲池提供的,而在 RDS 中来自磁盘(=EBS))。它可以与 MySQL 优化器相关(DO 和 RDS 可以选择不同的索引来服务查询 PRIMARY 与较小的二级索引)。但由于查询本身存在问题,这一切都无关紧要。

【讨论】:

  • 查询来自磁盘,数据集大于BP。我会比较 RDS 上的 EBS 卷和它们在 DO 上的 VM 中有什么?
  • 另外,你说RDS实例有2G RAM,而缓冲池是1G。 RDS使用swap很多吗?
  • RDS => 1000IOPS 保留 300GB SSD,DO VPS => 20GB 通用 SSD :)
  • DO 的 SDD 提供多少 IOPS?此外,单个 IO 响应时间对 MySQL 来说也很重要。 EBS毕竟是一个网络设备。与本地 SSD 相比,它将丢失。在 EC2 实例上,EBS 响应时间约为 2 毫秒,而本地卷(某些实例类型具有本地存储)提供约 0.2 毫秒。减少 10 倍!
  • 不管怎样,只要查询不是最优的,我就不会太在意底层硬件。
【解决方案2】:

您能否提供以下输出:

SHOW CREATE TABLE special_cargos;
SHOW GLOBAL VARIABLES LIKE 'innodb_buffer_pool_size';
EXPLAIN select count(special_cargo_id) from special_cargos;

在 RDS 和您的非 RDS 实例上?

暂时假设 special_cargo_id 是主键,它适合 RAM,并且 innodb_buffer_pool_size 配置合理(在具有 2GB RAM 的服务器上,1GB 是合理的数量,尽管 RDS 应该预先配置为一个合理的值),它应该在两个节点上运行类似。

我想到了两种可能的解释:

1) 在 RDS 上,您没有将 special_cargo_id 定义为 PK。

2) RDS 出于某种原因选择不使用索引(比较EXPLAIN 输出将确认是否发生这种情况)。

编辑:

实际上 - 你确定你的 5 美元 VPS 正在使用 InnoDB 吗?如果您在 0.08 秒内得到答案,那听起来它实际上并没有扫描索引。您很有可能在 VPS 上使用 MyISAM,它会在每次写入后更新表头中的行数,特别是让 SELECT COUNT(*) FROM table_name; 查询立即返回 - 就像您观察到的那样。

编辑 2:

哇 - 所以 VPS 配置了只有 128MB 的 innodb_buffer_pool_size 并且它仍然比配置了 1GB 的 innodb_buffer_pool_size 的 RDS 更快,而且两者的执行计划是一样的?

好的,试试这个:

select count(1) from special_cargos FORCE INDEX (PRIMARY);

【讨论】:

  • 刚刚做了。我的心有点炸了。我知道 RDS 很慢,但这已经超出了速度,这只是某处被彻底破坏了......
  • 从 special_cargos FORCE INDEX (PRIMARY) 中选择 count(1);这也是同时出现的
  • 是“从 special_cargos FORCE INDEX (index_special_cargos) 中选择 count(*);”更快吗?
  • @Christian 48 秒... :/
  • PRIMARY 会比让 Optmizer 选择“最小”索引要慢。
【解决方案3】:

当您只有 2GB 的 RAM 时,buffer_pool 的 1GB 非常高。可能那个系统正在疯狂地交换。

把它降低到 200M,看看它的运行速度。

看看他们是否有办法监控交换使用情况。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-24
    • 2022-06-14
    • 1970-01-01
    • 1970-01-01
    • 2012-09-21
    • 1970-01-01
    相关资源
    最近更新 更多