文档主页
MySQL 9.0 参考手册
相关文档 下载本手册
PDF (US Ltr) - 40.0Mb
PDF (A4) - 40.1Mb
手册页 (TGZ) - 258.2Kb
手册页 (Zip) - 365.3Kb
信息 (Gzip) - 4.0Mb
信息 (Zip) - 4.0Mb


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

10.4.4 MySQL 中的内部临时表使用

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

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

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

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

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

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

  • SHOW COLUMNS 语句和 DESCRIBE 语句对某些列使用 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:设置 TempTable 存储引擎在 MySQL 开始使用 InnoDB 磁盘上内部临时表之前允许从内存映射文件分配的最大内存量。默认设置为 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 9.0 仅使用 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 量。memory/temptable/physical_disk 报告当使用内存映射文件作为 TempTable 溢出机制时从磁盘分配的空间量。如果 physical_disk 工具报告的值不是 0,并且使用内存映射文件作为 TempTable 溢出机制,则表示在某个时间点达到了 TempTable 内存限制。可以在性能模式内存汇总表(例如 memory_summary_global_by_event_name)中查询数据。请参阅 第 29.12.20.10 节“内存汇总表”