Documentation Home
MySQL 8.4 Reference Manual
Related Documentation Download this Manual
PDF (US Ltr) - 39.8Mb
PDF (A4) - 39.9Mb
Man Pages (TGZ) - 257.9Kb
Man Pages (Zip) - 364.9Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 8.4 Reference Manual  /  ...  /  Internal Temporary Table Use in MySQL

10.4.4 MySQL 中内部临时表的使用

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

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

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

一些查询条件会阻止使用内存临时表,在这种情况下,服务器将使用磁盘表แทน:

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

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

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

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

以下条件使UNION语句在不使用临时表的情况下进行评估:

  • 并集是UNION ALL,而不是UNIONUNION DISTINCT

  • 没有全局的ORDER BY子句。

  • 并集不是一个{INSERT | REPLACE} ... SELECT ...语句的顶级查询块。

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

Storage Engine for In-Memory Internal Temporary 表

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

Note

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存储引擎可以使用的最大RAM大小,直到它开始从内存映射文件中分配空间或MySQL开始使用InnoDB磁盘内部临时表,取决于您的配置。默认temptable_max_ram设置值是服务器上的总内存的3%,最小和最大默认范围为1-4 GB。在MySQL 8.4之前,缺省值为1GiB。

    Note

    temptable_max_ram设置不考虑使用TempTable存储引擎的每个线程分配的线程本地内存块。线程本地内存块大小取决于线程的首次内存分配请求的大小。如果请求小于1MB,通常情况下是这样,那么线程本地内存块大小为1MB。如果请求大于1MB,那么线程本地内存块约与初始内存请求相同。线程本地内存块直到线程退出被保留在线程本地存储中。

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

    Note

    temptable_用mmap变量已弃用;在MySQL的未来版本中,预计将其支持移除。设置temptable_max_mmap=0等同于设置temptable_用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中。

使用internal_tmp_mem_storage_engine=MEMORY将内存临时表转换为磁盘表,如果该表变得太大。内存临时表的最大大小由tmp_ table_sizemax_heap_table_size值,取决于哪个值小。这个行为与使用CREATE TABLE创建的MEMORY表不同。在这种情况下,只有max_heap_table_size变量确定了表可以增长到多大,且不会将表转换为磁盘格式。

Storage Engine for On-Disk Internal Temporary 表

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 值。如果太多的内部临时表被创建到磁盘上,请考虑调整引擎特定的限制,详见 Internal Temporary Table Storage Engine

Note

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

性能_schema 中的memory/temptable/physical_rammemory/temptable/physical_disk工具可以用来监控TempTable空间分配情况。memory/temptable/physical_ram报告已分配的RAM大小。memory/temptable/physical_disk报告从磁盘中分配的空间大小,当使用内存映射文件作为 TempTable 溢出机制时。如果physical_disk工具报告的值不是0,并且使用内存映射文件作为 TempTable 溢出机制,那么某个时间点TempTable 内存限制被达到。可以在性能_schema 中的内存总结表中查询数据,例如memory_summary_global_by_event_name。请参阅第29.12.20.10节,“内存总结表”