跳转到

针对 MySQL 的性能优化提示

性能优化是管理任何数据库的关键方面。您可以从选择用于托管数据库服务器的硬件和软件组件,到数据模型设计和架构配置,在数据库管理的每个步骤中执行性能优化。本文档介绍了针对云端 MySQL 数据库的性能优化提示,尤其是 Cloud SQL for MySQL,包括实例化新数据库和优化现有的数据库。

硬件注意事项

硬件配置是数据库性能的重要考虑因素。在定义硬件配置之前,充分了解应用的活动和并发用户数量、数据库和索引的大小以及应用或服务的预期延迟时间非常重要。下面是一些重要的硬件注意事项:

中央处理器 (CPU)

处理能力是高性能数据库系统中最重要的因素之一。并发连接/用户/线程的数量决定了处理数据库请求所需的核心数量。分配给数据库的 CPU 需要能够处理正常工作负载 + 峰值(极端)工作负载,才能让应用以最佳水平运行。

对于 Cloud SQL(Google Cloud 的全代管式 MySQL 产品),CPU 以虚拟 CPU (vCPU) 的形式进行分配。 分配给数据库的 vCPU 数量最终决定了数据库实例的内存量和网络吞吐量,因为每个 vCPU 都有分配给它的最大内存量,甚至网络吞吐量也会根据 vCPU 的数量而变化。Cloud SQL 可让您灵活地调整实例的 vCPU 数量,从而轻松满足应用的内存和网络吞吐量要求。

内存

在确定要为数据库分配的内存量时,一个重要的考虑因素是确保工作集适合缓冲池。工作集是数据库随时使用的数据。分配的内存应足以保存此工作集或频繁访问的数据,这些数据通常由数据库数据、索引、会话缓冲区、字典缓存和哈希表组成。检查是否已分配足够的内存的一种方法是检查数据库中磁盘读取状态。 理想情况下,在正常工作负载条件下,磁盘读取应减少或极少。

如果分配给实例的内存不足,则实例可能会遇到“内存不足”问题,这些问题会导致数据库实例重启以及数据库或应用停机。

存储

数据库存储是影响性能优化的另一个组件。Cloud SQL 提供 2 种存储类型

  • SSD(默认)
  • HDD

与 HDD 相比,SSD 可提供更高的性能和吞吐量。 因此,始终选择 SSD 来提高性能,尤其是对于生产工作负载。

分配给实例的每秒读取和写入输入/输出操作数 (IOPS) 取决于创建实例时分配的存储空间量。磁盘大小越大,读写 IOPS 就越高。因此,建议您创建具有更高数据大小的实例,以获得更好的 IOPS 性能。以下 Google Cloud 控制台屏幕截图显示了创建时分配给数据库实例的资源摘要(包括最大容量),帮助用户确认并准确理解他们的数据库在实例化后将如何配置。

Google Cloud 控制台显示创建时分配给数据库实例的资源摘要(包括最大容量)
CloudSQL 还提供自选存储空间自动扩容功能。启用后,如果分配的存储空间低于指定阈值,此功能会自动增加额外的存储空间容量。

区域

缩短网络延迟时间的方法之一是选择距离应用或服务最近的实例区域。Cloud SQL for MySQL 可在所有 Google Cloud 区域使用,因此可让用户更轻松地将数据库尽可能靠近最终用户。

弹性扩缩

CloudSQL 提供了一种简单的方法来扩缩分配给数据库实例的资源(CPU、内存或存储空间)。这对于具有不同资源要求的工作负载非常有用。例如,用户可以在工作负载要求增加期间增加(纵向扩容)资源,然后在峰值工作负载结束时缩减资源。

MySQL 配置

本部分包含 MySQL 数据库配置提高性能的最佳实践。

版本

创建新数据库时,选择最新版本的 MySQL。与旧版本相比,最新版本修复了一些问题并进行了优化,以提升性能。Cloud SQL 提供市场上可用的最新版本的 MySQL,并在创建新数据库时将其设为默认版本。详细了解 Cloud SQL 支持的 MySQL 版本

InnoDB 缓冲区池大小

MySQL 实例仅支持一种存储引擎:InnoDB。Innodb 缓冲区池大小是用户为获得最佳性能而要定义的第一个参数。缓冲区池是分配给存储表缓存、索引缓存、清空前修改的数据以及自适应哈希索引 (AHI) 等其他内部结构的内存区域。

Cloud SQL 会根据实例大小定义要为 InnoDB 缓冲区池分配大约 72% 的实例内存的默认值(默认值因实例大小而异)。如需了解详情,请参阅不同实例大小的缓冲池设置。 Cloud SQL 可让您根据自己的应用需求使用数据库标志灵活地修改缓冲池大小。 

应调整缓冲区池大小,确保实例上有足够的可用内存供会话缓冲区、字典缓存、performance_schema 表(如果已启用)和 InnoDB 缓冲区池一起使用。

用户可以检查从实例发生的磁盘读取,以确定从磁盘读取的数据量与从缓冲池中读取到的数据量。如果磁盘读取次数较多,增加缓冲区池大小和实例内存会提高读取查询的性能。

重做日志/InnoDB 日志文件大小

InnoDB 日志文件或重做日志会记录对表数据的数据更改。InnoDB 日志文件大小定义了单个重做日志文件的大小。

对于具有较高重做日志大小的写入繁重的工作负载,可以为写入提供更多空间,而无需执行频繁的检查点刷新活动并节省磁盘 I/O,从而提高写入性能。重做日志的总大小,可以计算为 (innodb_log_file_size * innodb_log_files_in_group),在数据库访问繁忙的时候,应该足够容纳至少 1-2 小时的写入数据。

Cloud SQL 定义了 512 MB 的默认值。Cloud SQL 还可让您使用数据库标志灵活地增加 InnoDB 日志文件的大小。 

注意:增加 InnoDB 日志文件大小的值会增加崩溃恢复时间。

耐用性

innodb_flush_log_at_trx_commit 标志可控制日志数据刷新到磁盘的频率,以及是否针对每次事务提交刷新。

通过将 innodb_flush_log_at_trx_commit 的值更改为 0 或 2,可提高读取副本的写入性能。

Cloud SQL 不支持更改 Cloud SQL 主实例上的耐用性设置。但是,Cloud SQL 允许更改读取副本上的标志。降低读取副本的持久性可提高副本的写入性能。这有助于解决副本的复制延迟问题。 详细了解 innodb_flush_log_at_trx_commit

InnoDB 日志缓冲区大小

InnoDB 日志缓冲区大小是 InnoDB 用于写入日志文件(重做日志)的缓冲区量。

如果数据库中的事务(插入、更新或删除)较大,并且使用的缓冲区超过 16 MB,则 InnoDB 需要在提交事务之前执行磁盘 IO,这会影响性能。要避免磁盘 IO,请增加 innodb_log_buffer_size 的值。

Cloud SQL 为 InnoDB 日志缓冲区大小定义了一个默认值,即 16 MB。MySQL 状态变量 innodb_log_waits 显示 innodb_log_buffer_size 较小的次数,并且 InnoDB 在提交事务之前必须等待刷新发生。如果 innodb_log_waits 的值大于 0 并且正在增加,则使用数据库标志增加 innodb_log_buffer_size 的值以获得更好的性能。通过在 MySQL shell (CLI) 中运行以下查询,可以确定 innodb_log_buffer_sizeinnodb_log_waits 的值。这些查询显示了 MySQL 中的状态变量和全局变量的值。

SHOW GLOBAL VARIABLES LIKE 'innodb_log_buffer_size';

SHOW GLOBAL STATUS LIKE 'innodb_log_waits';

InnoDB IO 容量

InnoDB IO 容量定义了可用于后台任务的 IOPS 数量(例如,来自缓冲区池的页面刷新以及来自更改缓冲区的合并数据)。  

Cloud SQL 为 innodb_io_capacity 定义了 5,000 的默认值,为 innodb_io_capacity_max 定义了 10,000 的默认值。

此默认值最适用于大多数工作负载,但如果您的工作负载写入繁重或实例上未应用的更改很高,并且如果实例上有足够的 IOPS,则考虑增加 innodb_io_capacity 和 innodb_io_capacity_max。在 MySQL shell 中,您可以使用以下查询找到应用更改的值:

mysql -e 'show engine InnoDB status \G;' | grep Ibuf

会话缓冲区

会话缓冲区是为各个会话分配的内存。如果您的应用或查询包含大量的插入、更新、排序和联接操作,并且需要更高的缓冲区,则在为特定会话运行查询时定义高缓冲区值可避免性能开销。用户可以在全局级别阻止过多的缓冲区分配,而这会增加所有连接的值,进而增加实例的总内存用量。更改以下缓冲区的默认值有助于提高查询性能。您可以使用数据库标志更改这些值。

sort_buffer_size

join_buffer_size

tmp_table_size

max_heap_table_size

请注意,这些是每个会话的缓冲区值,提高限制可能会影响所有连接,最终可能导致总体内存用量增加。

Table_open_cache 和 Table_definition_cache

如果数据库实例(单个或多个数据库)中的表过多(超过数千个),请增加 table_open_cache 和 table_definition_cache 的值以加快打开表的速度。

table_definition_cache 可以加快表的打开速度,并且每个表只有一个条目。表定义缓存占用的空间较少,并且不使用文件描述符。如果字典对象缓存中的表实例数超出 table_definition_cache 限制,LRU 机制将开始标记要逐出的表实例,并最终将它们从字典对象缓存中删除,以便为新表定义腾出空间。每次打开新的表空间时,系统都会执行此过程。 只有非活跃的表空间才会关闭。这种逐出过程会减慢表的打开速度。

table_open_cache 定义了所有线程的打开表的数量。您可以通过检查 Opened_tables 状态变量来确认是否需要增加表缓存。如果 Opened_tables 的值很大,而且您不经常使用 FLUSH TABLES,那么可以考虑增加 table_open_cache 变量的值。

可以将 table_open_cache 和 table_definition_cache 设置为实例中的实际表数。详细了解 Cloud SQL high-number-of-open-tables Recommender

注意:Cloud SQL 提供了更改这些值的灵活性

架构建议

始终定义主键

定义表的主键会以物理方式组织数据,以便更快查找、检索和对记录进行排序,从而提升性能。

首选整数值自动递增的主键非常适合 OLTP 系统。

主键缺失也是导致基于行的复制场景的复制延迟的主要原因之一。

创建索引

创建索引有助于更快地检索数据,从而提升读取查询的性能。为查询的 WHERE、ORDER BY 和 GROUP BY 子句中使用的列创建索引。

注意:过多或未使用的索引也可能会影响数据库的性能。

性能优化的最佳实践

运行基准测试

运行性能测试或基准测试,看看配置是否是最佳的,或者是否可以通过调整硬件、MySQL 数据库或架构设计的配置来进一步改进配置。一次更改一个参数,并对照基准测试的结果,看看是否有所改进。

连接池

连接池是一种创建和管理连接池的技术,可供任何需要它们的进程使用。连接池可以大幅提高应用性能,同时减少总体资源用量。查看关于如何管理来自应用的连接(包括连接计数和超时)的详细信息。

将读取工作负载分配到读取副本

读取副本(多个可用区中的多个副本)可用于从主实例中分流读取工作负载。这样可以降低主实例的开销或负载,进而提升主实例的性能,还可为读取副本上的读取查询提供更多资源。 

ProxySQL 是一种能够路由数据库查询的高性能开源 MySQL 代理,可用于横向扩缩 Cloud SQL for MySQL 数据库

避免长时间运行的查询

我们知道,运行几分钟或几小时的查询会导致性能下降。

  • 撤消日志用于存储更改后行的旧版本以回滚事务,还用于在事务中提供一致的读取(数据快照)。这些撤消日志以链接列表的形式存储,近期版本指向旧版本,而旧版本则指向更旧的版本,以此类推。长时间运行的事务往往会延迟完全清除撤消日志的过程,从而增加撤消日志的列表。InnoDB 必须遍历大量的撤消日志和冗长的关联列表,这会降低性能。
  • 长时间运行的查询还会消耗资源(如内存、缓冲区和锁),这些资源不会长时间处于释放状态,并且会因缺少资源而影响其他查询。

避免大型事务

单个事务中太多的记录更改(更新、删除、插入)将占用太多记录的资源(锁、缓冲区)。可能会溢出日志缓冲区,从而产生磁盘 IO。其余查询必须等待资源或锁定被释放。这会导致向缓冲区池中放入过多数据,从而阻止进一步使用缓冲区池。回滚此类大型事务也会降低数据库的性能。 为了解决这个问题,建议将大事务拆分为运行更快的小型事务。

优化查询

始终优化查询以获得最佳结果,即资源更少、执行速度更快。查看针对 MySQL 查询调整的建议。

用于性能调整的工具

监控

Cloud SQL 为多个 Google Cloud 产品提供预定义的信息中心,包括默认的 Cloud SQL 监控信息中心。用户可以使用此信息中心来监控主实例和副本实例的整体运行状况。用户还可以创建自己的自定义信息中心,以显示他们感兴趣的指标。通过使用这些信息中心和指标,您可以使用之前列出的建议来识别和解决各种性能瓶颈(例如高 CPU 或高内存用量)。 提醒也可以根据这些指标进行配置。

慢查询标志

您可以在 Cloud SQL for MySQL 实例上启用慢查询标志,以标识执行时间超过 long_query_time 的查询。您可以进一步分析这些慢速查询并进行微调,从而提升性能。了解如何为 Cloud SQL 实例启用和检查慢速查询

性能架构

性能架构提供对 MySQL 实例的低级监控。 可以在内存大于 15 GB 的 Cloud SQL for MySQL 实例上启用性能架构。 系统架构 报告提供各种报告,以识别瓶颈、等待情况、缺少索引、内存使用情况等。

Query Insights

Query Insights 是 Cloud SQL 的原生功能,可以在其中分析查询以提高查询的性能。Query Insights 支持直观监控,并提供诊断信息,帮助您不仅仅通过检测来确定性能问题的根本原因。

性能建议

Cloud SQL high-number-of-tables Recommender 也是 Cloud SQL 的原生功能,它可以向 Cloud SQL 用户提供高性能建议以提升现有数据库的性能,还可以为定义配置提供建议以提高性能并降低实例费用。如需了解详情,请参阅 Cloud SQL 建议

Google Cloud 提供旨在满足您业务需求的代管式 MySQL 数据库,可以完成包括弃用本地数据中心、运行 SaaS 应用和迁移核心业务系统在内的各种任务。