Amazon Aurora
Aurora 用户指南
AWS 文档中描述的 AWS 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅中国的 AWS 服务入门

使用 Amazon Aurora MySQL 的并行查询

在下文中,您可以找到 Amazon Aurora 与 MySQL 的兼容性 的并行查询性能优化说明。该功能在某些数据密集型查询中使用特殊执行路径,从而利用 Aurora 共享存储架构。目前,与 MySQL 5.6 兼容的 Aurora MySQL 版本支持并行查询。并行查询非常适合以下 Aurora MySQL 数据库集群:具有包含数百万行的表以及需要数分钟或数小时才能完成的分析查询。

Aurora MySQL 的并行查询概述

Aurora MySQL 并行查询是一种优化功能,它并行处理在处理数据密集型查询时涉及的一些 I/O 和计算。并行处理的工作包括从存储中检索行,提取列值以及确定哪些行与 WHERE 子句和联接子句中的条件匹配。这种数据密集型工作将委派(在数据库优化术语中为向下推送)给 Aurora 分布式存储层中的多个节点。如果不使用并行查询,每个查询将所有扫描的数据传输到 Aurora MySQL 集群中的单个节点(头节点),并在此处执行所有查询处理。

如果启用了并行查询功能,Aurora MySQL 引擎将自动确定查询何时可以从中受益,而无需进行 SQL 更改(如提示或表属性)。在以下章节中,您可以找到何时将并行查询应用于查询的说明。您还可以了解如何确保在提供最大好处时应用并行查询。

注意

并行查询优化为需要数分钟或数小时才能完成的长时间运行的查询提供最大好处。Aurora MySQL 通常不会为低开销查询运行并行查询优化,或者在其他优化技术(例如查询缓存、缓冲池缓存或索引查找)更有意义时不会运行并行查询优化。如果发现在需要时未使用并行查询,请参阅验证哪些语句使用并行查询

优点

通过使用并行查询,您可以在 Aurora MySQL 表上运行数据密集型分析查询,在很多情况下,与传统的查询处理分工相比,性能提高了一个数量级。

并行查询的好处包括:

  • 由于跨多个存储节点并行处理物理读取请求,提高了 I/O 性能。

  • 减少了网络流量。Aurora 不会将存储节点中的整个数据页面传输到头节点并随后筛选掉不需要的行和列。相反,Aurora 传输仅包含结果集所需的列值的紧凑元组。

  • 由于向下推送 WHERE 子句的函数执行、行筛选和列投影,减少了头节点上的 CPU 使用率。

  • 减轻了缓冲池上的内存压力。并行查询处理的页面不会添加到缓冲池中,这会降低数据密集型扫描的可能性,从而将常用的数据从缓冲池中移出。

  • 通过使在现有的数据上执行长时间运行的分析查询变得切实可行,可能会在提取、转换和加载 (ETL) 管道中减少重复的数据。

架构

并行查询功能使用 Aurora MySQL 的主要架构准则:将数据库引擎与存储子系统分离,并简化通信协议以减少网络流量。Aurora MySQL 使用这些技术加快写入密集型操作,例如,重做日志处理。并行查询将相同的准则应用于读取操作。

注意

Aurora MySQL 并行查询的架构与其他数据库系统中具有类似名称的功能的架构不同。Aurora MySQL 并行查询不涉及对称多处理 (SMP),因此,不依赖于数据库服务器的 CPU 容量。并行执行是在存储层中发生的,与作为查询协调器的 Aurora MySQL 服务器无关。

默认情况下,如果没有并行查询,Aurora 查询处理涉及将原始数据传输到 Aurora 集群中的单个节点(头节点),并在该单个节点上的单个线程中执行所有进一步的处理。通过使用并行查询,该 I/O 密集型和 CPU 密集型工作的绝大部分将委派给存储层中的节点。仅将结果集的紧凑行传回到头节点,已筛选行并提取和转换了列值。性能优势来自于网络流量减少、头节点上的 CPU 使用率下降以及跨存储节点并行处理 I/O。并行 I/O、筛选和投影数量与运行查询的 Aurora 集群中的数据库实例数无关。

限制

以下限制适用于并行查询功能:

  • 目前,与 MySQL 5.6 兼容的 Aurora MySQL 版本支持并行查询。(请注意,PostgreSQL 数据库引擎具有一个不相关的功能,也称为“并行查询”。)

  • 目前,您只能在以下实例类中使用并行查询:

    • db.r3 系列中的所有实例类。

    • db.r4 系列中的所有实例类。

    • Aurora MySQL 在 db.r5 系列中支持的所有实例类。

    注意

    您无法为并行查询创建 db.t2 或 db.t3 实例。

  • 可以在以下区域中使用并行查询选项:

    • 美国东部(弗吉尼亚北部)

    • 美国东部(俄亥俄州)

    • 美国西部(俄勒冈)

    • 欧洲(爱尔兰)

    • 亚太区域(东京)

  • 要使用并行查询,需要创建新的集群或从现有的 Aurora MySQL 集群快照还原,如下所述。

  • 目前,Performance Insights 功能不适用于启用了并行查询的集群。

  • 目前,回溯功能不适用于启用了并行查询的集群。

  • 您无法停止和启动启用了并行查询的数据库集群。

  • 目前,分区表不支持并行查询。您可以在并行查询集群中使用分区表。对这些表进行的查询使用非并行查询执行路径。

    注意

    即使某些查询块引用分区表,联接、联合或其他多部分查询也可以部分使用并行查询。仅引用非分区表的查询块可以使用并行查询优化。

  • 目前,要使用并行查询,表必须使用 COMPACT 行格式,这需要使用 InnoDB 存储引擎的 Antelope 文件格式。

  • TEXTBLOBGEOMETRY 数据类型不支持并行查询。引用这些类型的任何列的查询无法使用并行查询。

  • 可变长度列(VARCHARCHAR 数据类型)与并行查询兼容,最大声明长度最多为 768 字节。如果查询引用的任何列具有使用更长最大长度声明的类型,则无法使用并行查询。对于使用多字节字符集的列,字节限制将字符集中的最大字节数考虑在内。例如,对于字符集 utf8mb4(最大字符长度为 4 字节),VARCHAR(192) 列与并行查询兼容,但 VARCHAR(193) 列不兼容。

    JSON 数据类型是与 BLOB 类似的类型,仅适用于与 MySQL 5.7 兼容的 Aurora。并行查询仅适用于与 MySQL 5.6 兼容的 Aurora。因此,目前在包含并行查询功能的集群上的表中不能包含该类型。

  • 目前,并行查询不用于包含全文搜索索引的表,而无论查询引用此类索引列还是使用 MATCH() 运算符。

  • 目前,并行查询不用于包含 LIMIT 子句的任何查询块。并行查询可能仍用于具有 GROUP by、ORDER BY 或联接的早期查询阶段。

  • 目前,关联子查询无法使用并行查询优化。

  • 并行查询适用于不写入或锁定的 SELECT 语句,并且仅在 REPEATABLE READ 隔离级别适用。例如,并行查询不能与 SELECT FOR UPDATE 或者 UPDATEDELETE 语句的 WHERE 子句一起使用。

  • 并行查询仅适用于没有挂起的快速联机数据定义语言 (DDL) 操作的表。

  • 并行查询功能适用于 WHERE 子句中的大多数(但不是全部)运算符和函数。有关说明兼容操作的示例,请参阅并行查询如何与 SQL 结构一起使用

  • 每个 Aurora 数据库实例每次只能运行一定数量的并行查询会话。如果查询具有多个使用并行查询的部分(例如,子查询、联接或 UNION 运算符),这些阶段将按顺序运行。在任何时候,该语句仅计为一个并行查询会话。您可以使用并行查询状态变量监控活动会话数。您可以查询 Aurora_pq_max_concurrent_requests 状态变量以检查给定数据库实例的并发会话数限制。

  • 目前,并行查询不支持 AWS Identity and Access Management (IAM) 数据库身份验证。

管理并行查询集群

管理启用了并行查询的集群需要执行设置步骤(创建或还原完整 Aurora MySQL 集群),以及确定在集群中启用并行查询的范围。

您可能需要创建经常使用并行查询的一些大型表的新版本,例如,将表指定为非分区表或删除全文搜索索引。有关详细信息,请参阅 创建架构对象以利用并行查询

在设置完成后,日常管理涉及监控性能并消除使用并行查询的障碍。有关这些说明,请参阅并行查询的性能优化

并行查询的升级注意事项

目前,您无法为 Aurora MySQL 集群执行就地升级以启用并行查询功能。要使用并行查询,需要创建新的集群或从现有的 Aurora MySQL 5.6 集群快照还原。

创建使用并行查询的数据库集群

要创建具有并行查询的 Aurora MySQL 集群,在其中添加新实例或执行其他管理操作,您可以使用与其他 Aurora MySQL 集群相同的 AWS 管理控制台和 AWS CLI 方法。您可以创建新的集群以使用并行查询。您也可以从 MySQL 5.6 兼容数据库快照还原,以便创建一个数据库集群以使用并行查询。如果不熟悉创建新的 Aurora MySQL 集群的过程,您可以在创建 Amazon Aurora 数据库集群中找到背景信息和先决条件。

不过,某些选项有所不同:

  • 在选择 Aurora MySQL 引擎版本时,请确保选择与 MySQL 5.6 兼容的最新引擎。目前,与 MySQL 5.6 兼容的 Aurora MySQL 版本支持并行查询。

  • 在创建或还原数据库集群时,请确保选择 parallelquery 引擎模式。

无论是创建新集群还是从快照还原,您都可以使用与其他 Aurora MySQL 集群相同的方法添加新的数据库实例。

使用控制台创建并行查询集群

您可以使用控制台创建新的并行查询集群,如下所述。

使用 AWS 管理控制台 创建并行查询集群

  1. 按照创建 Amazon Aurora 数据库集群中的常规 AWS 管理控制台过程进行操作。

  2. 选择引擎屏幕上,选择与 MySQL 5.6 兼容的 Aurora 版本。

  3. 指定数据库详细信息屏幕上,为容量类型选择启用 Aurora 并行查询的预配置,如下面的屏幕截图所示。

    
                  选择容量类型“Provisioned with Aurora parallel query enabled (在启用 Aurora 并行查询的情况下预配置)”

使用 AWS 管理控制台将快照还原到并行查询集群

  1. 找到与 MySQL 5.6 兼容的数据库实例快照。

  2. 按照从数据库集群快照还原中的常规 AWS 管理控制台过程进行操作。

  3. 对于数据库引擎模式,请选择 parallelquery,如下面的屏幕截图所示。

    
                  选择 aurora-mysql-pq

验证新集群是否可以使用并行查询

  1. 使用上述方法创建或还原集群。

  2. 检查 aurora_pq_supported 配置设置是否为 true。

    mysql> select @@aurora_pq_supported; +-----------------------+ | @@aurora_pq_supported | +-----------------------+ | 1 | +-----------------------+

使用 CLI 创建并行查询集群

您可以使用 CLI 创建新的并行查询集群,如下所述。

使用 AWS CLI 创建并行查询集群

  1. 检查哪些 Aurora MySQL 版本、AWS 实例类、AWS 区域、可用区等组合适用于并行查询集群。为此,请使用 aws rds describe-orderable-db-instance-options 命令,它生成 JSON 格式的输出。以下代码示例说明了如何检查哪些组合适用于指定 AWS 区域中的并行查询集群。

    aws rds describe-orderable-db-instance-options --engine aurora --query 'OrderableDBInstanceOptions[?contains(SupportedEngineModes,`parallelquery`)==`true`].{Engine:Engine,EngineVersion:EngineVersion,SupportedEngineModes:SupportedEngineModes,DBInstanceClass:DBInstanceClass}' --region us-east-1

    上述命令生成类似于以下内容的输出:

    [ { "DBInstanceClass": "db.r3.2xlarge", "EngineVersion": "5.6.10a", "Engine": "aurora", "SupportedEngineModes": [ "parallelquery" ] }, { "DBInstanceClass": "db.r3.4xlarge", "EngineVersion": "5.6.10a", ...
  2. 按照创建 Amazon Aurora 数据库集群中的常规 AWS CLI过程进行操作。

  3. 指定以下选项集:

    • 对于 --engine 选项,请使用 aurora

    • 对于 --engine-mode 选项,请使用 parallelquery--engine-mode 参数适用于 create-db-cluster 操作。然后,后续 create-db-instance 操作自动使用集群的引擎模式。

    • 对于 --engine-version 选项,请使用 5.6.10a

      以下代码示例显示了操作方法。

      aws rds create-db-cluster --db-cluster-identifier $CLUSTER_ID --engine aurora --engine-mode parallelquery --engine-version 5.6.10a \ --master-username $MASTER_USER_ID --master-user-password $MASTER_USER_PW \ --db-subnet-group-name $SUBNET_GROUP --vpc-security-group-ids $SECURITY_GROUP aws rds create-db-instance --db-instance-identifier ${INSTANCE_ID}-1 \ --engine aurora \ --db-cluster-identifier $CLUSTER_ID --db-instance-class $INSTANCE_CLASS
  4. 验证您创建或还原的集群是否具有可用的并行查询功能。检查 aurora_pq_supported 配置设置是否为 true。

    mysql> select @@aurora_pq_supported; +-----------------------+ | @@aurora_pq_supported | +-----------------------+ | 1 | +-----------------------+

使用 AWS CLI将快照还原到并行查询集群

  1. 检查哪些 Aurora MySQL 版本、AWS 实例类、AWS 区域、可用区等组合适用于并行查询集群。为此,请使用 aws rds describe-orderable-db-instance-options 命令,它生成 JSON 格式的输出。以下代码示例显示了操作方法。

    # See choices for a specified AWS Region. aws rds describe-orderable-db-instance-options --engine aurora --query 'OrderableDBInstanceOptions[?contains(SupportedEngineModes,`parallelquery`)==`true`].{Engine:Engine,EngineVersion:EngineVersion,SupportedEngineModes:SupportedEngineModes,DBInstanceClass:DBInstanceClass}' --region us-east-1 [ { "DBInstanceClass": "db.r3.2xlarge", "EngineVersion": "5.6.10a", "Engine": "aurora", "SupportedEngineModes": [ "parallelquery" ] }, { "DBInstanceClass": "db.r3.4xlarge", "EngineVersion": "5.6.10a", ...

  2. 从 MySQL 5.6 兼容数据库中找到一个快照。

  3. 按照从数据库集群快照还原中的常规 AWS CLI过程进行操作。

  4. 对于 --engine-mode 选项,请指定 parallelquery。以下代码示例显示了操作方法。

    aws rds restore-db-instance-from-db-snapshot \ --db-instance-identifier mynewdbinstance \ --db-snapshot-identifier mydbsnapshot \ --engine-mode parallelquery
  5. 验证您创建或还原的集群是否具有可用的并行查询功能。检查 aurora_pq_supported 配置设置是否为 true。

    mysql> select @@aurora_pq_supported; +-----------------------+ | @@aurora_pq_supported | +-----------------------+ | 1 | +-----------------------+

启用和禁用并行查询

您可以使用 aurora_pq 选项在数据库实例的全局和会话级别动态启用和禁用并行查询。在可以使用并行查询功能的集群上,将默认启用该参数。

mysql> select @@aurora_pq; +-------------+ | @@aurora_pq | +-------------+ | 1 | +-------------+

要在会话级别切换 aurora_pq 参数,例如,通过 mysql 命令行或在 JDBC 或 ODBC 应用程序中,请使用标准方法更改客户端配置设置。例如,标准 MySQL 客户端上的命令是 set session aurora_pq = {'ON'/'OFF'}。您还可以将会话级参数添加到 JDBC 配置或应用程序代码中,以动态启用或禁用并行查询。

目前,在更改 aurora_pq 参数的全局设置时,您必须为整个集群执行该操作,而不是为单个数据库实例执行该操作。要在集群级别切换 aurora_pq 参数,请使用处理参数组的方法,如使用数据库参数组和数据库集群参数组中所述。按照以下步骤进行操作:

  1. 创建自定义集群参数组。

  2. aurora_pq 更新为所需的值。

  3. 将自定义集群参数组附加到要使用并行查询功能的 Aurora 集群。

  4. 重新启动集群的所有数据库实例。

您可以使用 ModifyDBClusterParameterGroup API 操作或 AWS 管理控制台修改并行查询参数。

注意

如果启用了并行查询,Aurora MySQL 确定是否在运行时为每个查询使用该功能。对于联接、联合和子查询等,Aurora MySQL 确定每个查询块是否在运行时使用并行查询。有关详细信息,请参阅 验证哪些语句使用并行查询并行查询如何与 SQL 结构一起使用

使用控制台为数据库实例启用和禁用并行查询

您可以使用参数组在数据库实例级别启用或禁用并行查询。

使用 AWS 管理控制台为 Aurora MySQL 集群启用或禁用并行查询

  1. 创建一个自定义参数组,如使用数据库参数组和数据库集群参数组中所述。

  2. aurora_pq 更新为 0(已禁用)或 1(已启用),如以下屏幕截图所示。在可以使用并行查询功能的集群上,将默认启用 aurora_pq

  3. 将自定义集群参数组附加到要使用并行查询功能的 Aurora 数据库集群。

使用 CLI 为数据库实例启用和禁用并行查询

您可以使用 modify-db-cluster-parameter-group 命令修改并行查询参数。

使用 CLI 为数据库实例启用或禁用并行查询

  • 使用 modify-db-cluster-parameter-group 命令修改并行查询参数。

您还可以在会话级别启用或禁用并行查询,例如,通过 mysql 命令行或在 JDBC 或 ODBC 应用程序中。为此,请使用标准方法更改客户端配置设置。例如,标准 MySQL 客户端上的命令是 set session aurora_pq = {'ON'/'OFF'}

您还可以将会话级参数添加到 JDBC 配置或应用程序代码中,以动态启用或禁用并行查询。

并行查询的性能优化

要管理并行查询工作负载的性能,请确保将并行查询用于该优化最有用的查询。

为此,您可以执行以下操作:

  • 监控哪些查询使用并行查询。

  • 验证它是否用于大多数数据密集型查询和长时间运行的查询。

  • 微调集群上的条件以允许将并行查询应用于所需的查询,并以正确的并发级别为工作负载运行该查询。

创建架构对象以利用并行查询

由于并行查询要求表使用 ROW_FORMAT=Compact 设置,请检查 Aurora 配置设置以了解对 INNODB_FILE_FORMAT 配置选项的任何更改。(CREATE TABLE 语句上的替代 ROW_FORMAT 设置要求已将 INNODB_FILE_FORMAT 配置选项设置为 'Barracuda'。) 发出 SHOW TABLE STATUS 语句以确认数据库中的所有表的行格式。

目前,并行查询要求表为非分区表。因此,请检查 CREATE TABLE 语句和 SHOW CREATE TABLE 输出并删除任何 PARTITION BY 子句。对于现有的分区表,请先将数据复制到具有相同列定义和索引的非分区表中。然后,重命名旧表和新表,以便现有查询和 ETL 工作流使用非分区表。

在更改架构以允许并行查询使用更多表之前,请执行测试以确认并行查询是否导致净提高这些表的性能。此外,还要确保并行查询的架构要求与您的目标相符。

例如,在从 ROW_FORMAT=Compressed 切换到 ROW_FORMAT=Compact 之前,请针对原始表和新表测试工作负载的性能。此外,还要考虑其他潜在影响,例如,数据量增加。

验证哪些语句使用并行查询

在典型操作中,您无需执行任何特殊操作即可利用并行查询。在查询满足并行查询的基本要求后,查询优化程序自动确定是否在每个特定查询中使用并行查询。

如果您在开发或测试环境中运行试验,您可能会发现未使用并行查询,因为您的表的行数或总数据量太少。表的数据也可能完全位于缓冲池中,尤其是最近创建以执行试验的表。

在监控或优化集群性能时,您需要确定是否在相应的上下文中使用并行查询。您可以调整数据库架构、设置、SQL 查询甚至集群拓扑和应用程序连接设置以利用该功能。

要检查查询是否使用并行查询,请运行 EXPLAIN 语句以检查查询执行计划(也称为“解释计划”)。有关 SQL 语句、子句和表达式如何影响并行查询的 EXPLAIN 输出的示例,请参阅并行查询如何与 SQL 结构一起使用

以下示例说明了传统执行计划和并行查询计划之间的区别。该查询是 TPC-H 基准中的查询 3。本节中的很多示例查询使用 TPC-H 数据集中的表。

SELECT l_orderkey, sum(l_extendedprice * (1 - l_discount)) AS revenue, o_orderdate, o_shippriority FROM customer, orders, lineitem WHERE c_mktsegment = 'AUTOMOBILE' AND c_custkey = o_custkey AND l_orderkey = o_orderkey AND o_orderdate < date '1995-03-13' AND l_shipdate > date '1995-03-13' GROUP BY l_orderkey, o_orderdate, o_shippriority ORDER BY revenue DESC, o_orderdate LIMIT 10;

在禁用并行查询后,查询可能具有如下所示的执行计划,该计划使用哈希联接而不是并行查询。

+----+-------------+----------+...+-----------+-----------------------------------------------------------------+ | id | select_type | table |...| rows | Extra | +----+-------------+----------+...+-----------+-----------------------------------------------------------------+ | 1 | SIMPLE | customer |...| 5798330 | Using where; Using index; Using temporary; Using filesort | | 1 | SIMPLE | orders |...| 154545408 | Using where; Using join buffer (Hash Join Outer table orders) | | 1 | SIMPLE | lineitem |...| 606119300 | Using where; Using join buffer (Hash Join Outer table lineitem) | +----+-------------+----------+...+-----------+-----------------------------------------------------------------+

在启用并行查询后,该执行计划中的两个步骤可以使用并行查询优化,如 EXPLAIN 输出中的 Extra 列所示。这些步骤的 I/O 密集型和 CPU 密集型处理将向下推送到存储层。

+----+...+--------------------------------------------------------------------------------------------------------------------------------+ | id |...| Extra | +----+...+--------------------------------------------------------------------------------------------------------------------------------+ | 1 |...| Using where; Using index; Using temporary; Using filesort | | 1 |...| Using where; Using join buffer (Hash Join Outer table orders); Using parallel query (4 columns, 1 filters, 1 exprs; 0 extra) | | 1 |...| Using where; Using join buffer (Hash Join Outer table lineitem); Using parallel query (4 columns, 1 filters, 1 exprs; 0 extra) | +----+...+--------------------------------------------------------------------------------------------------------------------------------+

有关如何解释并行查询的 EXPLAIN 输出以及并行查询可以应用到的 SQL 语句部分的信息,请参阅并行查询如何与 SQL 结构一起使用

以下示例输出显示在具有冷缓冲池的 db.r4.2xlarge 实例上运行上述查询的结果。在使用并行查询时,查询运行速度要快得多。

注意

由于计时取决于很多环境因素,并且该示例查询使用早期版本的并行查询运行,因此,您的结果可能会有所不同。请始终执行您自己的性能测试,以便在您自己的环境、工作负载等条件下确认这些结果。

-- Without parallel query +------------+-------------+-------------+----------------+ | l_orderkey | revenue | o_orderdate | o_shippriority | +------------+-------------+-------------+----------------+ | 92511430 | 514726.4896 | 1995-03-06 | 0 | . . | 28840519 | 454748.2485 | 1995-03-08 | 0 | +------------+-------------+-------------+----------------+ 10 rows in set (24 min 49.99 sec)
-- With parallel query +------------+-------------+-------------+----------------+ | l_orderkey | revenue | o_orderdate | o_shippriority | +------------+-------------+-------------+----------------+ | 92511430 | 514726.4896 | 1995-03-06 | 0 | . . | 28840519 | 454748.2485 | 1995-03-08 | 0 | +------------+-------------+-------------+----------------+ 10 rows in set (1 min 49.91 sec)

本节中的很多示例查询使用该 TPC-H 数据集中的表,尤其是具有 2000 万行和以下定义的 PART 表。

+---------------+---------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +---------------+---------------+------+-----+---------+-------+ | p_partkey | int(11) | NO | PRI | NULL | | | p_name | varchar(55) | NO | | NULL | | | p_mfgr | char(25) | NO | | NULL | | | p_brand | char(10) | NO | | NULL | | | p_type | varchar(25) | NO | | NULL | | | p_size | int(11) | NO | | NULL | | | p_container | char(10) | NO | | NULL | | | p_retailprice | decimal(15,2) | NO | | NULL | | | p_comment | varchar(23) | NO | | NULL | | +---------------+---------------+------+-----+---------+-------+

在您的工作负载条件下试验,以了解各个 SQL 语句是否可以利用并行查询。然后,使用以下监控方法帮助验证在一段时间内在实际工作负载条件下使用并行查询的频率。对于实际工作负载,还存在额外的影响因素,例如,并发限制。

监控并行查询

除了监控 Amazon Aurora 数据库集群指标中所述的 Amazon CloudWatch 指标以外,Aurora 还提供了其他全局状态变量。您可以使用这些全局状态变量帮助监控并行查询执行,并使您了解优化程序在给定情况下可能使用或不使用并行查询的原因。要访问这些变量,您可以使用 SHOW GLOBAL STATUS 命令。您还可以找到在下面列出的这些变量。

并行查询会话并不一定具有与执行的查询之间的一一对应关系。例如,假设您的执行计划具有两个使用并行查询的步骤。在这种情况下,查询涉及两个并行会话,并且尝试的请求和成功请求的计数器增加 2 个。

在执行 EXPLAIN 语句以试验并行查询时,即使查询没有实际运行,也会看到指定为“未选择”的计数器增加。在生产环境中使用并行查询时,您可以检查“未选择”计数器的增加速度是否比预期速度快。然后,您可以调整集群设置、查询混合、启用了并行查询的数据库实例等,以便为所需的查询运行并行查询。

将在数据库实例级别跟踪这些计数器。在连接到不同的终端节点时,您可能会看到不同的指标,因为每个数据库实例运行自己的一组并行查询。如果读取器终端节点在每个会话中连接到不同的数据库实例,您可能也会看到不同的指标。

名称

说明

Aurora_pq_request_attempted

请求的并行查询会话数。该值可能表示每个查询具有多个会话,具体取决于 SQL 结构,如子查询和联接。

Aurora_pq_request_executed

成功运行的并行查询会话数。

Aurora_pq_request_failed

向客户端返回错误的并行查询会话数。在某些情况下,并行查询请求可能会失败,例如,由于在存储层中出现问题。在这些情况下,将使用非并行查询机制重试失败的查询部分。如果重试的查询也失败,则会向客户端返回错误并增加该计数器。

Aurora_pq_pages_pushed_down

并行查询避免通过网络传输到头节点的数据页面数量(每个页面具有 16 KiB 的固定大小)。

Aurora_pq_bytes_returned

在并行查询期间传输到头节点的元组数据结构的字节数。除以 16,384 以与 Aurora_pq_pages_pushed_down 进行比较。

Aurora_pq_request_not_chosen

未选择并行查询以满足查询条件的次数。该值是几个其他更精细的计数器的总和。即使未实际执行查询,EXPLAIN 语句可能也会增加该计数器。

Aurora_pq_request_not_chosen_below_min_rows

由于表中的行数而未选择并行查询的次数。即使未实际执行查询,EXPLAIN 语句可能也会增加该计数器。

Aurora_pq_request_not_chosen_small_table

由于表的总大小(由行数和平均行长度确定)而未选择并行查询的次数。即使未实际执行查询,EXPLAIN 语句可能也会增加该计数器。

Aurora_pq_request_not_chosen_high_buffer_pool_pct

由于在缓冲池中具有较高比例的表数据(目前大于 95%)而未选择并行查询的次数。在这些情况下,优化程序确定从缓冲池中读取数据更高效。即使未实际执行查询,EXPLAIN 语句可能也会增加该计数器。

Aurora_pq_request_not_chosen_few_pages_outside_buffer_pool

由于没有足够的未缓冲表数据以值得运行并行查询而未选择并行查询的次数,即使缓冲池中的表数据少于 95%。即使未实际执行查询,EXPLAIN 语句可能也会增加该计数器。

Aurora_pq_max_concurrent_requests

可以在该 Aurora 数据库实例上并发运行的最大并行查询会话数。这是一个取决于 AWS 实例类的固定数字。

Aurora_pq_request_in_progress

当前运行的并行查询会话数。该数字适用于您连接到的特定 Aurora 数据库实例,而不适用于整个 Aurora 数据库集群。要查看数据库实例是否接近其并发限制,请将该值与 Aurora_pq_max_concurrent_requests 进行比较。

Aurora_pq_request_throttled

由于在特定 Aurora 数据库实例上已运行的最大并发并行查询数而未选择并行查询的次数。

Aurora_pq_request_not_chosen_long_trx

由于正在长时间运行的事务中启动查询而使用非并行查询执行路径的并行查询请求数。即使未实际执行查询,EXPLAIN 语句可能也会增加该计数器。

Aurora_pq_request_not_chosen_unsupported_access

由于 WHERE 子句不符合并行查询条件而使用非并行查询执行路径的并行查询请求数。如果查询不需要数据密集型扫描,或者查询是 DELETEUPDATE 语句,则会出现该结果。

并行查询如何与 SQL 结构一起使用

在下一节中,您可以找到为什么特定 SQL 语句使用或不使用并行查询以及 Aurora MySQL 功能如何与并行查询交互的更详细信息。这些详细信息可以帮助您诊断使用并行查询的集群的性能问题,或了解并行查询如何应用于您的特定工作负载。

确定是否使用并行查询取决于在运行语句时存在的很多因素。因此,某些查询可能始终、从不或仅在某些情况下使用并行查询。

EXPLAIN 语句

正如本节中的示例所示,EXPLAIN 语句指示查询的每个阶段当前是否适合运行并行查询。它还指示可以将查询的哪些方面向下推送到存储层。执行计划中的最重要项目如下所示:

  • key 列的 NULL 以外的值表明可以使用索引查找高效地执行查询,而不会运行并行查询。

  • 较小的 rows 列值(即,不是数百万的值)表明查询没有访问足够的数据以值得运行并行查询,而不会运行并行查询。

  • Extra 列显示是否需要使用并行查询。该输出类似于以下示例。

    Using parallel query (A columns, B filters, C exprs; D extra)

    columns 数字表示查询块中引用的列数。

    filters 数字表示 WHERE 谓词数,它表示列值与常数的简单比较。比较可能是相等、不相等或范围。Aurora 可以最高效地并行处理这些类型的谓词。

    exprs 数字表示也可以并行处理但不像筛选条件那样高效的表达式数,例如,函数调用、运算符或其他表达式。

    extra 数字表示无法向下推送并由头节点执行的表达式数。

例如,请考虑以下 EXPLAIN 输出。

mysql> explain select p_name, p_mfgr from part -> where p_brand is not null -> and upper(p_type) is not null -> and round(p_retailprice) is not null; +----+-------------+-------+...+----------+----------------------------------------------------------------------------+ | id | select_type | table |...| rows | Extra | +----+-------------+-------+...+----------+----------------------------------------------------------------------------+ | 1 | SIMPLE | part |...| 20427936 | Using where; Using parallel query (5 columns, 1 filters, 2 exprs; 0 extra) | +----+-------------+-------+...+----------+----------------------------------------------------------------------------+

Extra 列中的信息显示从每行中提取 5 列以计算查询条件并构建结果集。一个 WHERE 谓词涉及一个筛选条件,即,在 WHERE 子句中直接测试的列。两个 WHERE 子句需要计算更复杂的表达式,在这种情况下,将涉及函数调用。0 extra 字段确认 WHERE 子句中的所有操作将作为并行查询处理的一部分向下推送到存储层。

如果未选择并行查询,您通常可以从 EXPLAIN 输出的其他列中推断出原因。例如,rows 值可能太小,或者 possible_keys 列可能表示查询可以使用索引查找,而不是数据密集型扫描。以下示例显示了一个查询,其中,优化程序可以根据主键的特性估计查询仅扫描少量的行。在这种情况下,不需要运行并行查询。

mysql> explain select count(*) from part where p_partkey between 1 and 100; +----+-------------+-------+-------+---------------+---------+---------+------+------+--------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+-------+---------------+---------+---------+------+------+--------------------------+ | 1 | SIMPLE | part | range | PRIMARY | PRIMARY | 4 | NULL | 99 | Using where; Using index | +----+-------------+-------+-------+---------------+---------+---------+------+------+--------------------------+

显示是否使用并行查询的输出考虑了在运行 EXPLAIN 语句时存在的所有因素。在实际运行查询时,如果在此期间情况发生变化,优化程序可能会做出不同的选择。例如,EXPLAIN 可能会报告语句将使用并行查询。但在以后实际运行查询时,它可能会根据此时的情况不使用并行查询。此类情况可能包括并发运行几个其他并行查询,从表中删除行,创建新的索引,在打开事务中经过的时间太长,等等。

WHERE 子句

要使查询使用并行查询优化,它必须 包含一个 WHERE 子句。

并行查询优化加快了 WHERE 子句中使用的多种类型的表达式的速度:

  • 列值与常数的简单比较,称为筛选条件。这些比较从向下推送到存储层中受益最多。将在 EXPLAIN 输出中报告查询中的筛选条件表达式数。

  • 如果可能,WHERE 子句中的其他类型的表达式也会向下推送到存储层。将在 EXPLAIN 输出中报告查询中的此类表达式数。这些表达式可能是函数调用、LIKE 运算符、CASE 表达式,等等。

  • 目前,并行查询不会向下推送某些函数和运算符。查询中的此类表达式数将在 EXPLAIN 输出中报告为 extra 计数器。查询的其余部分仍然可以使用并行查询。

  • 虽然不会向下推送选择列表中的表达式,但包含此类函数的查询仍然可以从并行查询的中间结果的网络流量减少中受益。例如,在选择列表中调用聚合函数的查询可以从并行查询中受益,即使不向下推送聚合函数。

例如,以下查询执行全表扫描并处理 P_BRAND 列的所有值。不过,它不使用并行查询,因为查询不包含任何 WHERE 子句。

mysql> explain select count(*), p_brand from part group by p_brand; +----+-------------+-------+------+---------------+------+---------+------+----------+---------------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+---------------+------+---------+------+----------+---------------------------------+ | 1 | SIMPLE | part | ALL | NULL | NULL | NULL | NULL | 20427936 | Using temporary; Using filesort | +----+-------------+-------+------+---------------+------+---------+------+----------+---------------------------------+

相反,以下查询包括筛选结果的 WHERE 谓词,因此,可以应用并行查询:

mysql> explain select count(*), p_brand from part where p_name is not null -> and p_mfgr in ('Manufacturer#1', 'Manufacturer#3') and p_retailprice > 1000 -> group by p_brand; +----+...+----------+-------------------------------------------------------------------------------------------------------------+ | id |...| rows | Extra | +----+...+----------+-------------------------------------------------------------------------------------------------------------+ | 1 |...| 20427936 | Using where; Using temporary; Using filesort; Using parallel query (5 columns, 1 filters, 2 exprs; 0 extra) | +----+...+----------+-------------------------------------------------------------------------------------------------------------+

如果优化程序估计查询块的返回行数很少,则不会在该查询块中使用并行查询。以下示例说明了一种主键列上的大于运算符应用于数百万行的情况,这会导致使用并行查询。估计反向小于测试仅应用于几行,而不使用并行查询。

mysql> explain select count(*) from part where p_partkey > 10; +----+...+----------+----------------------------------------------------------------------------+ | id |...| rows | Extra | +----+...+----------+----------------------------------------------------------------------------+ | 1 |...| 20427936 | Using where; Using parallel query (1 columns, 1 filters, 0 exprs; 0 extra) | +----+...+----------+----------------------------------------------------------------------------+ mysql> explain select count(*) from part where p_partkey < 10; +----+...+------+--------------------------+ | id |...| rows | Extra | +----+...+------+--------------------------+ | 1 |...| 9 | Using where; Using index | +----+...+------+--------------------------+

WHERE 子句中的函数调用

Aurora 可以将并行查询优化应用于 WHERE 子句中的大多数内置函数调用。并行处理这些函数调用将会从头节点中卸载一些 CPU 负载。通过在最早的查询阶段并行计算谓词函数,有助于 Aurora 最大限度减少在后续阶段传输和处理的数据量。

目前,并行处理不适用于选择列表中的函数调用。头节点计算这些函数,即使在 WHERE 子句中出现相同的函数调用。来自相关列的原始值包含在从存储节点发回到头节点的元组中。头节点执行任何转换(如 UPPER()CONCATENATE() 等)以生成结果集的最终值。

在以下示例中,并行查询将并行处理对 LOWER() 的调用,因为它出现在 WHERE 子句中。并行查询不会影响对 SUBSTR()UPPER() 的调用,因为它们出现在选择列表中。

mysql> explain select sql_no_cache distinct substr(upper(p_name),1,5) from part -> where lower(p_name) like '%cornflower%' or lower(p_name) like '%goldenrod%'; +----+...+---------------------------------------------------------------------------------------------+ | id |...| Extra | +----+...+---------------------------------------------------------------------------------------------+ | 1 |...| Using where; Using temporary; Using parallel query (2 columns, 0 filters, 1 exprs; 0 extra) | +----+...+---------------------------------------------------------------------------------------------+

相同的注意事项适用于其他表达式,例如,CASE 表达式或 LIKE 运算符。例如,以下示例显示并行查询计算 WHERE 子句中的 CASE 表达式和 LIKE 运算符。

mysql> explain select p_mfgr, p_retailprice from part -> where p_retailprice > case p_mfgr -> when 'Manufacturer#1' then 1000 -> when 'Manufacturer#2' then 1200 -> else 950 -> end -> and p_name like '%vanilla%' -> group by p_retailprice; +----+...+-------------------------------------------------------------------------------------------------------------+ | id |...| Extra | +----+...+-------------------------------------------------------------------------------------------------------------+ | 1 |...| Using where; Using temporary; Using filesort; Using parallel query (4 columns, 0 filters, 2 exprs; 0 extra) | +----+...+-------------------------------------------------------------------------------------------------------------+

聚合函数、GROUP BY 子句和 HAVING 子句

涉及聚合函数的查询通常是并行查询的理想之选,因为它们涉及扫描大型表中的大量行。选择列表或 HAVING 子句中的聚合函数调用不会向下推送到存储层。不过,并行查询仍然可以使用聚合函数提高此类查询的性能。为此,它先在存储层中从原始数据页面中并行提取列值。然后,它以紧凑元组格式将这些值发回到头节点,而不是作为完整数据页面。与往常一样,查询需要具有至少一个 WHERE 谓词才能激活并行查询。

以下简单示例说明了可以从并行查询中受益的聚合查询种类。它们以紧凑形式将中间结果返回到头节点以及/或者从中间结果中筛选不匹配的行。

mysql> explain select sql_no_cache count(distinct p_brand) from part where p_mfgr = 'Manufacturer#5'; +----+...+----------------------------------------------------------------------------+ | id |...| Extra | +----+...+----------------------------------------------------------------------------+ | 1 |...| Using where; Using parallel query (2 columns, 1 filters, 0 exprs; 0 extra) | +----+...+----------------------------------------------------------------------------+ mysql> explain select sql_no_cache p_mfgr from part where p_retailprice > 1000 group by p_mfgr having count(*) > 100; +----+...+-------------------------------------------------------------------------------------------------------------+ | id |...| Extra | +----+...+-------------------------------------------------------------------------------------------------------------+ | 1 |...| Using where; Using temporary; Using filesort; Using parallel query (3 columns, 0 filters, 1 exprs; 0 extra) | +----+...+-------------------------------------------------------------------------------------------------------------+

比较运算符

优化程序估计要扫描的行数以计算比较运算符,并根据该估计确定是否使用并行查询。

下面的第一个示例显示,可以在没有并行查询的情况下高效地执行与主键列的相等比较。下面的第二个示例显示,与未编制索引的列进行类似比较需要扫描数百万行,因此,可以从并行查询中受益。

mysql> explain select * from part where p_partkey = 10; +----+...+------+-------+ | id |...| rows | Extra | +----+...+------+-------+ | 1 |...| 1 | NULL | +----+...+------+-------+ mysql> explain select * from part where p_type = 'LARGE BRUSHED BRASS'; +----+...+----------+----------------------------------------------------------------------------+ | id |...| rows | Extra | +----+...+----------+----------------------------------------------------------------------------+ | 1 |...| 20427936 | Using where; Using parallel query (9 columns, 1 filters, 0 exprs; 0 extra) | +----+...+----------+----------------------------------------------------------------------------+

同样的注意事项适用于不等于测试和范围比较,例如小于、大于或等于或 BETWEEN。优化程序估计要扫描的行数,并根据 I/O 总量确定是否值得运行并行查询。

联接

大型表的联接查询通常涉及数据密集型操作,这些操作将从并行查询优化中受益。目前,不会并行处理多个表之间的列值比较(即,联接谓词本身)。不过,并行查询可以向下推送其他联接阶段的一些内部处理,例如,在哈希联接期间构建 Bloom 筛选条件。即使没有 WHERE 子句,并行查询也可以应用于联接查询。因此,对于需要使用 WHERE 子句以使用并行查询的规则,联接查询是一种例外情况。

将计算联接处理的每个阶段以检查它是否符合并行查询条件。如果多个阶段可以使用并行查询,将按顺序执行这些阶段。因此,每个联接查询在并发限制中计为单个并行查询会话。

例如,如果联接查询包含 WHERE 谓词以筛选联接的某个表中的行,该筛选选项可以使用并行查询。作为另一个示例,假设联接查询使用哈希联接机制,例如,将大表与小表联接在一起。在这种情况下,用于生成 Bloom 筛选条件数据结构的表扫描或许可以使用并行查询。

注意

虽然哈希联接功能目前需要启用实验室模式,但哈希联接在启用了并行查询的集群中始终可用。

mysql> explain select count(*) from orders join customer where o_custkey = c_custkey; +----+...+----------+-------+---------------+-------------+...+-----------+-----------------------------------------------------------------------------------------------------------------+ | id |...| table | type | possible_keys | key |...| rows | Extra | +----+...+----------+-------+---------------+-------------+...+-----------+-----------------------------------------------------------------------------------------------------------------+ | 1 |...| customer | index | PRIMARY | c_nationkey |...| 15051972 | Using index | | 1 |...| orders | ALL | o_custkey | NULL |...| 154545408 | Using join buffer (Hash Join Outer table orders); Using parallel query (1 columns, 0 filters, 1 exprs; 0 extra) | +----+...+----------+-------+---------------+-------------+...+-----------+-----------------------------------------------------------------------------------------------------------------+

对于使用嵌套循环机制的联接查询,最外层的嵌套循环块可能会使用并行查询。是否使用并行查询取决于与往常相同的因素,例如,是否在 WHERE 子句中存在其他筛选条件。

mysql> -- Nested loop join with extra filter conditions can use parallel query. mysql> explain select count(*) from part, partsupp where p_partkey != ps_partkey and p_name is not null and ps_availqty > 0; +----+-------------+----------+...+----------+----------------------------------------------------------------------------+ | id | select_type | table |...| rows | Extra | +----+-------------+----------+...+----------+----------------------------------------------------------------------------+ | 1 | SIMPLE | part |...| 20427936 | Using where; Using parallel query (2 columns, 1 filters, 0 exprs; 0 extra) | | 1 | SIMPLE | partsupp |...| 78164450 | Using where; Using join buffer (Block Nested Loop) | +----+-------------+----------+...+----------+----------------------------------------------------------------------------+

子查询

对于每个块,根据表和 WHERE 子句等的通常特性,外部查询块和内部子查询块可能会分别使用或不使用并行查询。例如,以下查询在子查询块中使用并行查询,但在外部块中不使用并行查询。

mysql> explain select count(*) from part where --> p_partkey < (select max(p_partkey) from part where p_name like '%vanilla%'); +----+-------------+...+----------+----------------------------------------------------------------------------+ | id | select_type |...| rows | Extra | +----+-------------+...+----------+----------------------------------------------------------------------------+ | 1 | PRIMARY |...| NULL | Impossible WHERE noticed after reading const tables | | 2 | SUBQUERY |...| 20427936 | Using where; Using parallel query (2 columns, 0 filters, 1 exprs; 0 extra) | +----+-------------+...+----------+----------------------------------------------------------------------------+

联合

对于 UNION 的每个部分,根据表和 WHERE 子句等的通常特性,UNION 查询中的每个查询块可能会使用或不使用并行查询。

mysql> explain select p_partkey from part where p_name like '%choco_ate%' -> union select p_partkey from part where p_name like '%vanil_a%'; +----+----------------+...+----------+----------------------------------------------------------------------------+ | id | select_type |...| rows | Extra | +----+----------------+...+----------+----------------------------------------------------------------------------+ | 1 | PRIMARY |...| 20427936 | Using where; Using parallel query (2 columns, 0 filters, 1 exprs; 0 extra) | | 2 | UNION |...| 20427936 | Using where; Using parallel query (2 columns, 0 filters, 1 exprs; 0 extra) | | NULL | UNION RESULT | <union1,2> |...| NULL | Using temporary | +----+--------------+...+----------+----------------------------------------------------------------------------+

注意

查询中的每个 UNION 子句是按顺序运行的。即使查询包含的多个阶段均使用并行查询,它在任何时间也仅运行单个并行查询。因此,甚至是复杂的多阶段查询也仅在并发并行查询限制中计为 1 个。

视图

优化程序将视图作为使用基础表的较长查询以重写任何查询。因此,无论表引用是视图还是实际表,并行查询的工作方式都是相同的。有关在查询中是否使用并行查询以及向下推送哪些部分的所有相同注意事项适用于最终重写的查询。

例如,以下执行计划显示了通常不使用并行查询的视图定义。在使用额外的 WHERE 子句查询视图时,Aurora MySQL 使用并行查询。

mysql> create view part_view as select * from part; mysql> explain select count(*) from part_view where p_partkey is not null; +----+...+----------+----------------------------------------------------------------------------+ | id |...| rows | Extra | +----+...+----------+----------------------------------------------------------------------------+ | 1 |...| 20427936 | Using where; Using parallel query (1 columns, 0 filters, 0 exprs; 1 extra) | +----+...+----------+----------------------------------------------------------------------------+

数据操作语言 (DML) 语句

如果 SELECT 部分满足并行查询的其他条件,则 INSERT 语句可以在 SELECT 处理阶段中使用并行查询。

mysql> explain insert into part_subset select * from part where p_mfgr = 'Manufacturer#1'; +----+...+----------+----------------------------------------------------------------------------+ | id |...| rows | Extra | +----+...+----------+----------------------------------------------------------------------------+ | 1 |...| 20427936 | Using where; Using parallel query (9 columns, 1 filters, 0 exprs; 0 extra) | +----+...+----------+----------------------------------------------------------------------------+

注意

通常,在执行 INSERT 语句后,新插入的行的数据将位于缓冲池中。因此,在插入大量行后,表可能不符合并行查询条件。以后,在正常运行期间从缓冲池中移出数据后,针对表的查询可能会再次开始使用并行查询。

CREATE TABLE AS SELECT 语句不使用并行查询,即使该语句的 SELECT 部分符合并行查询条件。该语句的 DDL 特性导致它与并行查询处理不兼容。相反,在 INSERT ... SELECT 语句中,SELECT 部分可以使用并行查询。

DELETEUPDATE 语句中从不使用并行查询,而无论表的大小和 WHERE 子句中的谓词如何。

mysql> explain delete from part where p_name is not null; +----+-------------+...+----------+-------------+ | id | select_type |...| rows | Extra | +----+-------------+...+----------+-------------+ | 1 | SIMPLE |...| 20427936 | Using where | +----+-------------+...+----------+-------------+

事务和锁定

并行查询仅适用于在 REPEATABLE READ 隔离级别执行的语句。该隔离级别是可以在作为只读副本的 Aurora 数据库实例上设置的唯一级别。您可以在 Aurora 主实例上使用所有隔离级别。

在较大的事务完成后,表统计数据可能会过时。这种过时的统计数据可能要求使用 ANALYZE TABLE 语句,然后 Aurora 才能准确估计行数。大型 DML 语句可能还会将大部分的表数据放入缓冲池中。将该数据放入缓冲池可能会导致不常为该表选择并行查询,直到将数据从池中移出。

如果您的会话位于长时间运行的事务中(默认为 10 分钟),则该会话中的其他查询不会使用并行查询。在单个长时间运行的查询期间,也可能会发生超时。如果查询在并行查询处理开始之前运行的时间超过最大间隔(当前为 10 分钟),则可能会发生这种超时。

您可以在执行临时(一次)查询的 mysql 会话中设置 autocommit=1,以降低意外启动长时间运行的事务的可能性。甚至针对表的 SELECT 语句也可以创建读取视图以开始运行事务。读取视图 是一个用于后续查询的一致数据集,将在提交事务之前保留该数据集。在 Aurora 中使用 JDBC 或 ODBC 应用程序时,也要注意该限制,因为此类应用程序可能会在禁用 autocommit 设置的情况下运行。

以下示例显示对表运行查询如何创建一个读取视图以隐式开始运行事务(在禁用了 autocommit 设置的情况下)。稍后运行的查询仍然可以使用并行查询。不过,在暂停几分钟后,查询不再符合并行查询条件。如果将事务以 COMMITROLLBACK 结尾,将恢复并行查询条件。

mysql> set autocommit=0; mysql> explain select sql_no_cache count(*) from part_txn where p_retailprice > 10.0; +----+...+---------+----------------------------------------------------------------------------+ | id |...| rows | Extra | +----+...+---------+----------------------------------------------------------------------------+ | 1 |...| 2976129 | Using where; Using parallel query (1 columns, 1 filters, 0 exprs; 0 extra) | +----+...+---------+----------------------------------------------------------------------------+ mysql> select sleep(720); explain select sql_no_cache count(*) from part_txn where p_retailprice > 10.0; +------------+ | sleep(720) | +------------+ | 0 | +------------+ 1 row in set (12 min 0.00 sec) +----+...+---------+-------------+ | id |...| rows | Extra | +----+...+---------+-------------+ | 1 |...| 2976129 | Using where | +----+...+---------+-------------+ mysql> commit; mysql> explain select sql_no_cache count(*) from part_txn where p_retailprice > 10.0; +----+...+---------+----------------------------------------------------------------------------+ | id |...| rows | Extra | +----+...+---------+----------------------------------------------------------------------------+ | 1 |...| 2976129 | Using where; Using parallel query (1 columns, 1 filters, 0 exprs; 0 extra) | +----+...+---------+----------------------------------------------------------------------------+

要查看查询由于位于长时间运行的事务中而不符合并行查询条件的次数,请检查 Aurora_pq_not_chosen_long_trx 状态变量。

mysql> show global status like '%pq%trx%'; +-------------------------------+-------+ | Variable_name | Value | +-------------------------------+-------+ | Aurora_pq_not_chosen_long_trx | 4 | +-------------------------------+-------+

获取锁定的任何 SELECT 语句(如 SELECT FOR UPDATESELECT LOCK IN SHARE MODE 语法)无法使用并行查询。

并行查询可以用于 LOCK TABLES 语句锁定的表。

mysql> explain select o_orderpriority, o_shippriority from orders where o_clerk = 'Clerk#000095055'; +----+...+-----------+----------------------------------------------------------------------------+ | id |...| rows | Extra | +----+...+-----------+----------------------------------------------------------------------------+ | 1 |...| 154545408 | Using where; Using parallel query (3 columns, 1 filters, 0 exprs; 0 extra) | +----+...+-----------+----------------------------------------------------------------------------+ mysql> explain select o_orderpriority, o_shippriority from orders where o_clerk = 'Clerk#000095055' for update; +----+...+-----------+-------------+ | id |...| rows | Extra | +----+...+-----------+-------------+ | 1 |...| 154545408 | Using where | +----+...+-----------+-------------+

索引

根据每个列的数据特性,ANALYZE TABLE 语句收集的统计数据可以帮助优化程序确定何时使用并行查询或索引查找。在执行对表中的数据进行重大更改的 DML 操作后,请运行 ANALYZE TABLE 以将统计数据保持最新状态。

如果索引查找可以在没有数据密集型扫描的情况下高效地执行查询,则 Aurora 可能会使用索引查找。这样做可以避免并行查询处理的开销。可以在任何 Aurora 数据库集群上同时运行的并行查询数也存在并发限制。确保使用最佳实践为表编制索引,以便最频繁和最高并发性的查询使用索引查找。

内置缓存机制

Aurora 包括内置缓存机制,即,缓冲池和查询缓存。Aurora 优化程序在这些缓存机制和并行查询之间进行选择,具体取决于哪一个对特定查询最有效。

在并行查询筛选行并转换和提取列值时,数据将作为元组而不是数据页面传回到头节点。因此,运行并行查询不会将任何页面添加到缓冲池中,也不会移出已位于缓冲池中的页面。

Aurora 检查位于缓冲池中的表数据的页数,以及该数字所占的表数据比例。Aurora 使用该信息确定使用并行查询(并绕过缓冲池中的数据)是否更高效。或者,Aurora 可能使用非并行查询执行路径,这会使用缓冲池中缓存的数据。缓存哪些页面以及数据密集型查询如何影响缓存和移出取决于与缓冲池相关的配置设置。因此,很难预测任何特定查询是否使用并行查询,因为这取决于缓冲池中不断变化的数据。

此外,Aurora 对并行查询施加并发限制。由于并非每个查询都使用并行查询,多个查询同时访问的表通常将大部分数据放在缓冲池中。因此,Aurora 通常不会选择这些表以运行并行查询。

在同一个表上运行一系列非并行查询时,由于数据没有位于缓冲池中,第一个查询的速度可能很慢。由于缓冲池现已“预热”,第二次和后续查询要快得多。并行查询通常从针对表的第一个查询开始就具有一致的性能。在进行性能测试时,将使用冷缓冲池和热缓冲池对非并行查询进行基准测试。在某些情况下,使用热缓冲池的结果可能与并行查询时间接近。在这些情况下,请考虑一些因素,例如,针对该表的查询频率以及是否值得在缓冲池中保留该表的数据。

在提交相同的查询以及未更改基础表数据时,查询缓存可以避免重新执行查询。并行查询功能优化的查询可以放入查询缓存中,实际上可以在再次运行时立即运行它们。

注意

在进行性能比较时,查询缓存可能会生成虚假的低计时数。因此,在与基准测试类似的情况下,您可以使用 sql_no_cache 提示。该提示可以防止从查询缓存中提供结果,即使以前运行了相同的查询。该提示直接位于查询中的 SELECT 语句后面。本主题中的很多并行查询示例包括该提示,以使启用和未启用并行查询的查询版本具有类似的查询时间。

在生产环境中使用并行查询时,请确保从源中删除该提示。

MyISAM 临时表

并行查询优化仅适用于 InnoDB 表。由于 Aurora MySQL 在后台的临时表中使用 MyISAM,因此,涉及临时表的内部查询阶段从不使用并行查询。这些查询阶段由 EXPLAIN 输出中的 Using temporary 指示。