### 8.4.4 MySQL 内部临时表的使用

[](<>)

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

服务器在以下条件下创建临时表：

-   评估[`联盟`](union.html)语句，有一些例外情况稍后描述。

-   评估一些观点，例如那些使用`可取的`算法，[`联盟`](union.html)，或聚合。

-   派生表的评估（见[第 13.2.11.8 节，“派生表”](derived-tables.html)）。

-   公用表表达式的求值（参见[第 13.2.15 节，“WITH（公用表表达式）”](with.html)）。

-   为子查询或半联接实现创建的表（请参阅[第 8.2.2 节，“优化子查询、派生表、视图引用和公用表表达式”](subquery-optimization.html)）。

-   评估包含`订购方式`子句和不同的`通过...分组`条款，或`订购方式`要么`通过...分组`包含来自连接队列中第一个表以外的表的列。

-   评估`清楚的`结合`订购方式`可能需要一个临时表。

-   对于使用`SQL_SMALL_RESULT`修饰符，MySQL 使用内存中的临时表，除非查询还包含需要磁盘存储的元素（稍后描述）。

-   评估[`插入...选择`](insert-select.html)从同一个表中选择和插入的语句，MySQL 创建一个内部临时表来保存来自[`选择`](select.html)，然后将这些行插入到目标表中。看[第 13.2.6.1 节，“INSERT ... SELECT 语句”](insert-select.html).

-   多表评估[`更新`](update.html)陈述。

-   评估[`GROUP_CONCAT()`](aggregate-functions.html#function_group-concat)要么[`计数（不同）`](aggregate-functions.html#function_count)表达式。

-   窗函数的评估（见[第 12.21 节，“窗口函数”](window-functions.html)) 根据需要使用临时表。

    要确定语句是否需要临时表，请使用[`解释`](explain.html)并检查`额外的`列看看它是否说`使用临时`（看[第 8.8.1 节，“使用 EXPLAIN 优化查询”](using-explain.html)）。`解释`不一定说`使用临时`对于派生或物化临时表。对于使用窗口函数的语句，[`解释`](explain.html)和`格式=JSON`始终提供有关窗口步骤的信息。如果窗口函数使用临时表，则为每个步骤指明。

    某些查询条件会阻止使用内存中的临时表，在这种情况下，服务器会使用磁盘表来代替：

-   的存在[`斑点`](blob.html)要么[`文本`](blob.html)表中的列。然而`临时表`存储引擎是 MySQL 8.0 中内存内部临时表的默认存储引擎，从 MySQL 8.0.13 开始支持二进制大对象类型。看[内部临时表存储引擎](internal-temporary-tables.html#internal-temporary-tables-engines).

-   在[`选择`](select.html)列出，如果[`联盟`](union.html)要么[`联合所有`](union.html)用来。

-   这[`显示列`](show-columns.html)和[`描述`](describe.html)语句使用`斑点`作为某些列的类型，因此用于结果的临时表是磁盘上的表。

    服务器不使用临时表来存储数据[`协会`](union.html)符合某些条件的声明。相反，它从临时表创建中只保留执行结果列类型转换所需的数据结构。该表没有完全实例化，没有写入或读取任何行；行直接发送到客户端。结果是减少了内存和磁盘需求，并且在第一行被发送到客户机之前的延迟更小，因为服务器不需要等到执行最后一个查询块。[`解释`](explain.html)优化器跟踪输出反映了这种执行策略：`联合结果`查询块不存在，因为该块对应于从临时表读取的部分。

    这些条件都符合a的条件`协会`对于没有临时表格的评估：

-   工会是`联合所有`不`协会`或`独特联盟`.

-   没有全球性的`订购人`条款

-   union不是查询的顶级查询块`{插入|替换}。。。选择`陈述

#### 内部临时表存储引擎

内部临时表可以保存在内存中，并由`诱人的`或`记忆力`存储引擎，或由`InnoDB`存储引擎。

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

这个[`内部存储引擎`](server-system-variables.html#sysvar_internal_tmp_mem_storage_engine)变量定义用于内存内部临时表的存储引擎。允许值为`诱人的`（默认）和`记忆力`.

笔记

从MySQL 8.0.27开始，为[`内部存储引擎`](server-system-variables.html#sysvar_internal_tmp_mem_storage_engine)需要[`会话变量管理`](privileges-provided.html#priv_session-variables-admin)或[`系统变量管理`](privileges-provided.html#priv_system-variables-admin)特权

这个`诱人的`存储引擎为用户提供高效的存储[`瓦尔查尔`](char.html)和[`VARBINARY`](binary-varbinary.html)列，以及MySQL 8.0.13中的其他二进制大对象类型。

以下变量控制着诱人的存储引擎限制和行为：

-   [`tmp_表_尺寸`](server-system-variables.html#sysvar_tmp_table_size)：来自MySQL 8.0.28，[`tmp_表_尺寸`](server-system-variables.html#sysvar_tmp_table_size)定义由可诱惑存储引擎创建的任何单个内存内部临时表的最大大小。当[`tmp_表_尺寸`](server-system-variables.html#sysvar_tmp_table_size)达到限制后，MySQL会自动将内存中的内部临时表转换为`InnoDB`磁盘上的内部临时表。默认值[`tmp_表_尺寸`](server-system-variables.html#sysvar_tmp_table_size)设置为16777216字节（16 MiB）。

    这个[`tmp_表_尺寸`](server-system-variables.html#sysvar_tmp_table_size)限制旨在防止单个查询消耗过多的全局可诱惑资源，这可能会影响需要可诱惑资源的并发查询的性能。全球诱人的资源由[`诱人的_max_ram`](server-system-variables.html#sysvar_temptable_max_ram)和[`诱人的_max_mmap`](server-system-variables.html#sysvar_temptable_max_mmap)设置。

    如果[`tmp_表_尺寸`](server-system-variables.html#sysvar_tmp_table_size)限制小于[`诱人的_max_ram`](server-system-variables.html#sysvar_temptable_max_ram)限制，内存中的临时表不可能包含超出[`tmp_表_尺寸`](server-system-variables.html#sysvar_tmp_table_size)限度如果[`tmp_表_尺寸`](server-system-variables.html#sysvar_tmp_table_size)限制大于[`诱人的_max_ram`](server-system-variables.html#sysvar_temptable_max_ram)和[`诱人的_max_mmap`](server-system-variables.html#sysvar_temptable_max_mmap)限制，内存中的临时表不可能包含超过[`诱人的_max_ram`](server-system-variables.html#sysvar_temptable_max_ram)和[`诱人的_max_mmap`](server-system-variables.html#sysvar_temptable_max_mmap)限制。

-   [`诱人的_max_ram`](server-system-variables.html#sysvar_temptable_max_ram)：定义可由服务器使用的最大RAM量`诱人的`在存储引擎开始从内存映射文件分配空间之前，或者在MySQL开始使用`InnoDB`磁盘上的内部临时表，具体取决于您的配置。默认值[`诱人的_max_ram`](server-system-variables.html#sysvar_temptable_max_ram)设置为1073741824字节（1GiB）。

    笔记

    这个[`诱人的_max_ram`](server-system-variables.html#sysvar_temptable_max_ram)设置不考虑分配给每个使用线程的线程的线程本地内存块`诱人的`存储引擎。线程本地内存块的大小取决于线程的第一个内存分配请求的大小。如果请求小于1MB，在大多数情况下，线程本地内存块大小为1MB。如果请求大于1MB，则线程本地内存块的大小与初始内存请求大致相同。线程本地内存块保存在线程本地存储器中，直到线程退出。

-   [`诱人的_使用_mmap`](server-system-variables.html#sysvar_temptable_use_mmap)：控制`诱人的`存储引擎从内存映射文件或MySQL使用中分配空间`InnoDB`当[`诱人的_max_ram`](server-system-variables.html#sysvar_temptable_max_ram)超出限制。默认设置为[`诱人的_use_mmap=ON`](server-system-variables.html#sysvar_temptable_use_mmap).

    笔记

    这个[`诱人的_使用_mmap`](server-system-variables.html#sysvar_temptable_use_mmap)变量在MySQL 8.0.16中引入，在MySQL 8.0.26中被弃用；预计MySQL的未来版本将删除对它的支持。背景[`诱人的_max_mmap=0`](server-system-variables.html#sysvar_temptable_max_mmap)相当于设置[`诱人的_使用_mmap=OFF`](server-system-variables.html#sysvar_temptable_use_mmap).

-   [`诱人的_max_mmap`](server-system-variables.html#sysvar_temptable_max_mmap)：在MySQL 8.0.23中引入。定义在MySQL开始使用之前，诱惑存储引擎允许从内存映射文件分配的最大内存量`InnoDB`磁盘上的内部临时表。默认设置为1073741824字节（1GiB）。该限制旨在解决内存映射文件在临时目录中使用过多空间的风险([`tmpdir`](server-system-variables.html#sysvar_tmpdir)).A[`诱人的_max_mmap=0`](server-system-variables.html#sysvar_temptable_max_mmap)该设置将禁用内存映射文件的分配，从而有效地禁用它们的使用，而不考虑[`诱人的_使用_mmap`](server-system-variables.html#sysvar_temptable_use_mmap)背景

    用户对内存映射文件的使用`诱人的`存储引擎受以下规则管辖：

-   临时文件是在[`tmpdir`](server-system-variables.html#sysvar_tmpdir)变量

-   临时文件在创建和打开后会立即被删除，因此不会在系统中保持可见[`tmpdir`](server-system-variables.html#sysvar_tmpdir)目录临时文件占用的空间在临时文件打开时由操作系统保留。当用户关闭临时文件时，空间将被回收`诱人的`存储引擎，或者`mysqld`进程被关闭。

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

-   如果空间在规定的限制范围内可用，则新数据存储在RAM中[`诱人的_max_ram`](server-system-variables.html#sysvar_temptable_max_ram)。否则，新数据将存储在临时文件中。

-   如果在一个表的一些数据被写入临时文件后，RAM中的空间变得可用，那么剩余的表数据就有可能存储在RAM中。

    当使用`记忆力`内存中临时表的存储引擎([`内部存储引擎=内存`](server-system-variables.html#sysvar_internal_tmp_mem_storage_engine))，如果内存中的临时表太大，MySQL会自动将其转换为磁盘上的表。内存中临时表的最大大小由[`tmp_表_尺寸`](server-system-variables.html#sysvar_tmp_table_size)或[`最大堆大小表大小`](server-system-variables.html#sysvar_max_heap_table_size)值，以较小者为准。这与`记忆力`使用显式创建的表[`创建表格`](create-table.html).对于此类表格，只有[`最大堆大小表大小`](server-system-variables.html#sysvar_max_heap_table_size)变量决定一个表可以增长多大，并且不需要转换为磁盘格式。

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

在MySQL 8.0.15及更早版本中[`内部\u tmp\u磁盘\u存储\u引擎`](server-system-variables.html#sysvar_internal_tmp_disk_storage_engine)变量定义了用于磁盘内部临时表的存储引擎。支持的存储引擎`InnoDB`和`米萨姆`.

从MySQL 8.0.16开始，MySQL只使用`InnoDB`磁盘上内部临时表的存储引擎。这个`米萨姆`存储引擎不再支持用于此目的。

`InnoDB`磁盘上的内部临时表是在默认情况下位于数据目录中的会话临时表空间中创建的。有关更多信息，请参阅[第15.6.3.5节，“临时表空间”](innodb-temporary-tablespace.html).

在MySQL 8.0.15及更早版本中：

-   对于公共表表达式（CTE），磁盘内部临时表所用的存储引擎不能`米萨姆`如果[`内部\u tmp\u磁盘\u存储\u引擎=MYISAM`](server-system-variables.html#sysvar_internal_tmp_disk_storage_engine)，任何尝试使用磁盘上临时表具体化CTE的操作都会出错。

-   使用时[`内部\u tmp\u磁盘\u存储\u引擎=INNODB`](server-system-variables.html#sysvar_internal_tmp_disk_storage_engine)，查询生成的磁盘内部临时表超过`InnoDB`行或列限制返回行大小过大或列过多错误。解决方法是设置[`内部\u tmp\u磁盘\u存储\u引擎`](server-system-variables.html#sysvar_internal_tmp_disk_storage_engine)到`米萨姆`.

#### 内部临时表存储格式

当内存中的内部临时表由`诱人的`存储引擎，包括`瓦尔查尔`柱，`VARBINARY`列和其他二进制大对象类型列（MySQL 8.0.13支持）在内存中由一个单元格数组表示，每个单元格包含一个空标志、数据长度和一个数据指针。列值按连续顺序放置在数组之后，在单个内存区域中，无需填充。阵列中的每个单元使用16字节的存储空间。当`诱人的`存储引擎从内存映射文件中分配空间。

当内存中的内部临时表由`记忆力`存储引擎，使用固定长度的行格式。`瓦尔查尔`和`VARBINARY`列值被填充到最大列长度，实际上将它们存储为`烧焦`和`二进制的`柱。

在MySQL 8.0.16之前，磁盘上的内部临时表由`InnoDB`或`米萨姆`存储引擎（取决于[`内部\u tmp\u磁盘\u存储\u引擎`](server-system-variables.html#sysvar_internal_tmp_disk_storage_engine)设置）。两个引擎都使用动态宽度行格式存储内部临时表。列只占用所需的存储空间，与使用固定长度行的磁盘表相比，这减少了磁盘I/O、空间需求和处理时间。从MySQL 8.0.16开始，[`内部\u tmp\u磁盘\u存储\u引擎`](server-system-variables.html#sysvar_internal_tmp_disk_storage_engine)不支持，并且磁盘上的内部临时表始终由`InnoDB`.

当使用`记忆力`在存储引擎中，语句最初可以创建内存中的内部临时表，如果表太大，则可以将其转换为磁盘上的表。在这种情况下，可以通过跳过转换并首先在磁盘上创建内部临时表来实现更好的性能。这个[`大桌子`](server-system-variables.html#sysvar_big_tables)变量可用于强制内部临时表的磁盘存储。

#### 监视内部临时表的创建

在内存或磁盘上创建内部临时表时，服务器会增加[`创建了_tmp_表`](server-status-variables.html#statvar_Created_tmp_tables)价值在磁盘上创建内部临时表时，服务器会增加[`创建了_tmp_disk_表`](server-status-variables.html#statvar_Created_tmp_disk_tables)价值如果在磁盘上创建了太多的内部临时表，则考虑调整所描述的引擎特定限制。[内部临时表存储引擎](internal-temporary-tables.html#internal-temporary-tables-engines).

笔记

由于已知的限制，[`创建了_tmp_disk_表`](server-status-variables.html#statvar_Created_tmp_disk_tables)不依赖于在内存映射文件中创建的磁盘临时表。默认情况下，诱人的存储引擎溢出机制会在内存映射文件中创建内部临时表。看见[内部临时表存储引擎](internal-temporary-tables.html#internal-temporary-tables-engines).

这个`内存/可诱惑/物理内存`和`内存/可诱惑/物理磁盘`性能模式工具可用于监控`诱人的`从内存和磁盘分配空间。`内存/可诱惑/物理内存`报告分配的RAM数量。`内存/可诱惑/物理磁盘`报告当内存映射文件用作诱人的溢出机制时从磁盘分配的空间量。如果`物理磁盘`仪器报告0以外的值，并且内存映射文件被用作可诱惑的溢出机制，在某个点达到了可诱惑的内存限制。可以在性能模式内存摘要表中查询数据，例如[`内存\u摘要\u全局\u按事件\u名称`](performance-schema-memory-summary-tables.html)看见[第27.12.20.10节，“内存汇总表”](performance-schema-memory-summary-tables.html).
