MySQL 没有充分利用服务器
MySQL does not utilize server fully
我在 Amazon RDS 数据库上安装了 MariaDB 10.0.17 运行。m4.xlarge(16Gb RAM,4vCPU)多可用区部署。我们使用最大设置为 10000 IOPS 的预配置 IOPS 存储。
users
table包含17M条记录; user_properties
table 包含 350M 条记录。
user_properties
table 描述 "map" 附加到用户的道具。 upkey
是键,string_value
、integer_value
等是每种类型的值;字符串、日期、整数、双精度。索引也是按类型的。
我们尝试向 user_properties
table 插入更多数据:应用程序将数据插入 INNODB temp table TEMP1
,然后从 [=19] 复制数据=] 至 user_properties
table.
问题是我们只能达到 2500 写入 IOPS 和 500-1000 读取 IOPS。队列深度平均保持在 ~7。 MySQL 服务器 CPU 使用率保持在 20-30%,从未达到 60%。
应用程序似乎向 MySQL 提供了足够的数据:我们将类似的数据文件提供给数据库,并查看处理时间如何随着 table 大小的增加而增加。
大多数时间应用程序等待 MySQL 查询完成。在此过程中,插入 TEMP1
table 只占总时间的一小部分,大部分时间是等待从 TEMP1
table 插入到 user_properties
.
有人可以帮助我提高 MySQL 速度吗?我应该怎么办increase/change?
CREATE TABLE IF NOT EXISTS `users` (
`id` bigint(20), // Column is not used now. Filled with NULL
`version` bigint(20) NOT NULL,
`email` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`uuid` varchar(80) COLLATE utf8_unicode_ci DEFAULT NULL,
`partner_id` bigint(20) NOT NULL,
`password` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`date_created` datetime DEFAULT NULL,
`last_updated` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `unique-email` (`partner_id`,`email`),
UNIQUE KEY `users_Uuid` (`uuid`),
KEY `idx_013_partner_id_uuid` (`partner_id`,`uuid`),
KEY `idx_014_uuid` (`uuid`),
CONSTRAINT `FKB2D9FEBE725C505E` FOREIGN KEY (`partner_id`) REFERENCES `partner` (`id`),
CONSTRAINT `fk_046_partner` FOREIGN KEY (`partner_id`) REFERENCES `partner` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
CREATE TABLE IF NOT EXISTS `user_properties` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`version` bigint(20) NOT NULL,
`date_created` datetime DEFAULT NULL,
`last_updated` datetime DEFAULT NULL,
`upkey` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`user_id` bigint(20) DEFAULT NULL,
`security_level` int(11) NOT NULL,
`_content` longtext COLLATE utf8_unicode_ci NOT NULL,
`class` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`date_value` datetime DEFAULT NULL,
`integer_value` bigint(20) DEFAULT NULL,
`double_value` double DEFAULT NULL,
`string_value` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`uuid` varchar(80) COLLATE utf8_unicode_ci DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `idx_004_uuid` (`uuid`),
KEY `idx_005_string_value` (`upkey`,`string_value`),
KEY `idx_006_integer_value` (`upkey`,`integer_value`),
KEY `idx_007_double_value` (`upkey`,`double_value`),
KEY `idx_008_date_value` (`upkey`,`date_value`),
KEY `idx_key_value_user_upkey_string` (`user_id`,`upkey`,`string_value`),
CONSTRAINT `FK_users` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
id
和 uuid
都需要吗?我觉得不是。
table 需要 3 个 UNIQUE
键吗?我想不是。 (记住 PRIMARY KEY
是 UNIQUE
。)
当 table 变大时,uuid
有一些非常糟糕的 I/O 属性。重新考虑您对它们的使用。 uuid
上的索引 非常 随机。当索引(或 table)变得太大而无法放入 buffer_pool 时,提取往往涉及 I/O 而不是缓存。对于 350M 行和 16GB RAM,我怀疑性能问题的很大一部分是由于 uuid。
user_properties
是 "key-value" 商店,对吗?该架构设计模式很糟糕。什么是典型的SELECT
?我怀疑是这样的:
SELECT ..._value FROM user_properties
WHERE user_id = '...'
AND upkey = '...';
假设这是正确的,可以通过
提高性能
PRIMARY KEY(user_id, upkey, id)
这将 "cluster" 给定用户的键值对位于单个位置(可能是 1-2 个块),从而加快获取速度。
有关 evils of key-value 的更多信息和改进建议。
更多关于 evils of UUIDs.
我在 Amazon RDS 数据库上安装了 MariaDB 10.0.17 运行。m4.xlarge(16Gb RAM,4vCPU)多可用区部署。我们使用最大设置为 10000 IOPS 的预配置 IOPS 存储。
users
table包含17M条记录; user_properties
table 包含 350M 条记录。
user_properties
table 描述 "map" 附加到用户的道具。 upkey
是键,string_value
、integer_value
等是每种类型的值;字符串、日期、整数、双精度。索引也是按类型的。
我们尝试向 user_properties
table 插入更多数据:应用程序将数据插入 INNODB temp table TEMP1
,然后从 [=19] 复制数据=] 至 user_properties
table.
问题是我们只能达到 2500 写入 IOPS 和 500-1000 读取 IOPS。队列深度平均保持在 ~7。 MySQL 服务器 CPU 使用率保持在 20-30%,从未达到 60%。
应用程序似乎向 MySQL 提供了足够的数据:我们将类似的数据文件提供给数据库,并查看处理时间如何随着 table 大小的增加而增加。
大多数时间应用程序等待 MySQL 查询完成。在此过程中,插入 TEMP1
table 只占总时间的一小部分,大部分时间是等待从 TEMP1
table 插入到 user_properties
.
有人可以帮助我提高 MySQL 速度吗?我应该怎么办increase/change?
CREATE TABLE IF NOT EXISTS `users` (
`id` bigint(20), // Column is not used now. Filled with NULL
`version` bigint(20) NOT NULL,
`email` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`uuid` varchar(80) COLLATE utf8_unicode_ci DEFAULT NULL,
`partner_id` bigint(20) NOT NULL,
`password` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`date_created` datetime DEFAULT NULL,
`last_updated` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `unique-email` (`partner_id`,`email`),
UNIQUE KEY `users_Uuid` (`uuid`),
KEY `idx_013_partner_id_uuid` (`partner_id`,`uuid`),
KEY `idx_014_uuid` (`uuid`),
CONSTRAINT `FKB2D9FEBE725C505E` FOREIGN KEY (`partner_id`) REFERENCES `partner` (`id`),
CONSTRAINT `fk_046_partner` FOREIGN KEY (`partner_id`) REFERENCES `partner` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
CREATE TABLE IF NOT EXISTS `user_properties` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`version` bigint(20) NOT NULL,
`date_created` datetime DEFAULT NULL,
`last_updated` datetime DEFAULT NULL,
`upkey` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`user_id` bigint(20) DEFAULT NULL,
`security_level` int(11) NOT NULL,
`_content` longtext COLLATE utf8_unicode_ci NOT NULL,
`class` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`date_value` datetime DEFAULT NULL,
`integer_value` bigint(20) DEFAULT NULL,
`double_value` double DEFAULT NULL,
`string_value` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`uuid` varchar(80) COLLATE utf8_unicode_ci DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `idx_004_uuid` (`uuid`),
KEY `idx_005_string_value` (`upkey`,`string_value`),
KEY `idx_006_integer_value` (`upkey`,`integer_value`),
KEY `idx_007_double_value` (`upkey`,`double_value`),
KEY `idx_008_date_value` (`upkey`,`date_value`),
KEY `idx_key_value_user_upkey_string` (`user_id`,`upkey`,`string_value`),
CONSTRAINT `FK_users` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
id
和 uuid
都需要吗?我觉得不是。
table 需要 3 个 UNIQUE
键吗?我想不是。 (记住 PRIMARY KEY
是 UNIQUE
。)
uuid
有一些非常糟糕的 I/O 属性。重新考虑您对它们的使用。 uuid
上的索引 非常 随机。当索引(或 table)变得太大而无法放入 buffer_pool 时,提取往往涉及 I/O 而不是缓存。对于 350M 行和 16GB RAM,我怀疑性能问题的很大一部分是由于 uuid。
user_properties
是 "key-value" 商店,对吗?该架构设计模式很糟糕。什么是典型的SELECT
?我怀疑是这样的:
SELECT ..._value FROM user_properties
WHERE user_id = '...'
AND upkey = '...';
假设这是正确的,可以通过
提高性能PRIMARY KEY(user_id, upkey, id)
这将 "cluster" 给定用户的键值对位于单个位置(可能是 1-2 个块),从而加快获取速度。
有关 evils of key-value 的更多信息和改进建议。
更多关于 evils of UUIDs.