文档首页
MySQL 8.4 参考手册
相关文档 下载本手册
PDF(美国信纸) - 39.9 MB
PDF(A4) - 40.0 MB
手册页(TGZ) - 258.5 KB
手册页(Zip) - 365.5 KB
信息(Gzip) - 4.0 MB
信息(Zip) - 4.0 MB


MySQL 8.4 参考手册  /  ...  /  MySQL 中的内部临时表使用

10.4.4 MySQL 中的内部临时表使用

在某些情况下,服务器会在处理语句时创建内部临时表。用户无法直接控制何时发生这种情况。

服务器会在以下情况下创建临时表:

要确定语句是否需要临时表,请使用 EXPLAIN 并检查 Extra 列,看看它是否显示 Using temporary(请参阅 第 10.8.1 节“使用 EXPLAIN 优化查询”)。对于派生或物化临时表,EXPLAIN 不一定显示 Using temporary。对于使用窗口函数的语句,使用 FORMAT=JSONEXPLAIN 始终提供有关窗口步骤的信息。如果窗口函数使用临时表,则会在每个步骤中指示。

某些查询条件会阻止使用内存中临时表,在这种情况下,服务器会改用磁盘表:

  • 表中存在 BLOBTEXT 列。TempTable 存储引擎是 MySQL 8.4 中内存中内部临时表的默认存储引擎,它支持二进制大对象类型。请参阅 内部临时表存储引擎

  • 如果使用了 UNIONUNION ALL,则 SELECT 列表中存在任何最大长度大于 512(二进制字符串为字节,非二进制字符串为字符)的字符串列。

  • SHOW COLUMNSDESCRIBE 语句对某些列使用 BLOB 类型,因此用于结果的临时表是磁盘上的表。

对于满足某些条件的 UNION 语句,服务器不使用临时表。相反,它仅保留临时表创建中执行结果列类型转换所需的数据结构。该表未完全实例化,并且没有行写入或从中读取;行直接发送到客户端。结果是减少了内存和磁盘需求,并且缩短了将第一行发送到客户端之前的延迟,因为服务器不需要等到最后一个查询块执行完毕。 EXPLAIN 和优化器跟踪输出反映了此执行策略:UNION RESULT 查询块不存在,因为该块对应于从临时表读取的部分。

以下条件使 UNION 有资格在没有临时表的情况下进行评估

  • 该联合是 UNION ALL,而不是 UNIONUNION DISTINCT

  • 没有全局 ORDER BY 子句。

  • 该联合不是 {INSERT | REPLACE} ... SELECT ... 语句的顶级查询块。

内部临时表存储引擎

内部临时表可以保存在内存中并由 TempTableMEMORY 存储引擎处理,也可以由 InnoDB 存储引擎存储在磁盘上。

内存中内部临时表的存储引擎

internal_tmp_mem_storage_engine 变量定义用于内存中内部临时表的存储引擎。允许的值为 TempTable(默认值)和 MEMORY

注意

internal_tmp_mem_storage_engine 配置会话设置需要 SESSION_VARIABLES_ADMINSYSTEM_VARIABLES_ADMIN 权限。

TempTable 存储引擎为 VARCHARVARBINARY 列以及其他二进制大对象类型提供高效存储。

以下变量控制 TempTable 存储引擎的限制和行为

  • tmp_table_size:定义由 TempTable 存储引擎创建的任何单个内存中内部临时表的最大大小。当达到 tmp_table_size 限制时,MySQL 会自动将内存中内部临时表转换为 InnoDB 磁盘上内部临时表。默认的 tmp_table_size 设置为 16777216 字节(16 MiB)。

    tmp_table_size 限制旨在防止单个查询消耗过多的全局 TempTable 资源,这会影响需要 TempTable 资源的并发查询的性能。全局 TempTable 资源由 temptable_max_ramtemptable_max_mmap 设置控制。

    如果 tmp_table_size 限制小于 temptable_max_ram 限制,则内存中临时表不可能包含超过 tmp_table_size 限制允许的数据。如果 tmp_table_size 限制大于 temptable_max_ramtemptable_max_mmap 限制的总和,则内存中临时表不可能包含超过 temptable_max_ramtemptable_max_mmap 限制总和的数据。

  • temptable_max_ram:定义在 TempTable 存储引擎开始从内存映射文件分配空间或 MySQL 开始使用 InnoDB 磁盘上内部临时表之前(取决于您的配置)可以使用的最大 RAM 量。默认的 temptable_max_ram 设置值为服务器可用总内存的 3%,最小和最大默认范围为 1-4 GB。在 MySQL 8.4 之前,默认值为 1GiB。

    注意

    temptable_max_ram 设置不考虑分配给使用 TempTable 存储引擎的每个线程的线程本地内存块。线程本地内存块的大小取决于线程的第一个内存分配请求的大小。如果请求小于 1MB(在大多数情况下是这样),则线程本地内存块大小为 1MB。如果请求大于 1MB,则线程本地内存块的大小与初始内存请求的大小大致相同。线程本地内存块保存在线程本地存储中,直到线程退出。

  • temptable_use_mmap:控制当超过 temptable_max_ram 限制时,TempTable 存储引擎是否从内存映射文件分配空间或 MySQL 是否使用 InnoDB 磁盘上内部临时表。默认设置为 temptable_use_mmap=OFF

    注意

    temptable_use_mmap 变量已弃用;预计在未来版本的 MySQL 中将删除对它的支持。设置 temptable_max_mmap=0 等效于设置 temptable_use_mmap=OFF

  • temptable_max_mmap:设置在 MySQL 开始使用 InnoDB 磁盘上内部临时表之前,允许 TempTable 存储引擎从内存映射文件分配的最大内存量。默认设置为 0(禁用)。此限制旨在解决内存映射文件在临时目录(tmpdir)中使用过多空间的风险。 temptable_max_mmap = 0 禁用从内存映射文件分配,从而有效地禁用它们的使用,而不管 temptable_use_mmap 设置如何。

TempTable 存储引擎对内存映射文件的使用受以下规则约束

  • 临时文件是在 tmpdir 变量定义的目录中创建的。

  • 临时文件在创建和打开后立即删除,因此在 tmpdir 目录中不可见。临时文件占用的空间由操作系统在临时文件打开时持有。当 TempTable 存储引擎关闭临时文件或 mysqld 进程关闭时,将回收该空间。

  • 数据永远不会在 RAM 和临时文件之间、RAM 内或临时文件之间移动。

  • 如果在 temptable_max_ram 定义的限制内有可用空间,则新数据将存储在 RAM 中。否则,新数据将存储在临时文件中。

  • 如果在将表的某些数据写入临时文件后 RAM 中有可用空间,则剩余的表数据可能会存储在 RAM 中。

当对内存中临时表使用 MEMORY 存储引擎时(internal_tmp_mem_storage_engine=MEMORY),如果内存中临时表变得太大,MySQL 会自动将其转换为磁盘上的表。内存中临时表的最大大小由 tmp_table_sizemax_heap_table_size 值(以较小者为准)定义。这与使用 CREATE TABLE 显式创建的 MEMORY 表不同。对于此类表,只有 max_heap_table_size 变量决定表可以增长多大,并且不会转换为磁盘格式。

磁盘上内部临时表的存储引擎

MySQL 8.4 仅使用 InnoDB 存储引擎来处理磁盘上的内部临时表。(不再支持 MYISAM 存储引擎用于此目的。)

InnoDB 磁盘上内部临时表是在会话临时表空间中创建的,默认情况下,这些表空间位于数据目录中。有关更多信息,请参阅 第 17.6.3.5 节“临时表空间”

内部临时表存储格式

当内存中内部临时表由 TempTable 存储引擎管理时,包含 VARCHAR 列、VARBINARY 列和其他二进制大对象类型列的行在内存中由一个单元格数组表示,每个单元格包含一个 NULL 标志、数据长度和数据指针。列值按顺序放置在数组之后,位于单个内存区域中,没有填充。数组中的每个单元格使用 16 个字节的存储空间。当 TempTable 存储引擎从内存映射文件分配空间时,将应用相同的存储格式。

当内存中内部临时表由 MEMORY 存储引擎管理时,将使用固定长度行格式。 VARCHARVARBINARY 列值将填充到最大列长度,实际上是将它们存储为 CHARBINARY 列。

磁盘上的内部临时表始终由 InnoDB 管理。

当使用 MEMORY 存储引擎时,语句最初可以创建一个内存中内部临时表,然后如果该表变得太大,则将其转换为磁盘上的表。在这种情况下,通过跳过转换并首先在磁盘上创建内部临时表,可能会获得更好的性能。 big_tables 变量可用于强制将内部临时表存储在磁盘上。

监控内部临时表创建

当在内存或磁盘上创建内部临时表时,服务器会增加 Created_tmp_tables 的值。当在磁盘上创建内部临时表时,服务器会增加 Created_tmp_disk_tables 的值。如果在磁盘上创建了过多的内部临时表,请考虑调整 内部临时表存储引擎 中描述的引擎特定限制。

注意

由于已知的限制,Created_tmp_disk_tables 不统计在内存映射文件中创建的磁盘临时表。默认情况下,TempTable 存储引擎溢出机制会在内存映射文件中创建内部临时表。请参阅 内部临时表存储引擎

可以使用 memory/temptable/physical_rammemory/temptable/physical_disk 性能模式工具来监视从内存和磁盘分配的 TempTable 空间。 memory/temptable/physical_ram 报告已分配的 RAM 量。当使用内存映射文件作为 TempTable 溢出机制时,memory/temptable/physical_disk 会报告从磁盘分配的空间量。如果 physical_disk 工具报告的值不是 0 并且使用内存映射文件作为 TempTable 溢出机制,则表示在某个时间点达到了 TempTable 内存限制。可以在性能模式内存摘要表(如 memory_summary_global_by_event_name)中查询数据。请参阅 第 29.12.20.10 节“内存摘要表”