8.4.4 MySQL 中的内部临时 table 使用

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

服务器在以下条件下创建临时 table:

要确定语句是否需要临时 table,请使用EXPLAIN并检查Extra列以查看其是否 table 示Using temporary(请参见第 8.8.1 节“使用 EXPLAIN 优化查询”)。对于派生的或物化的临时 table,EXPLAIN不一定会说Using temporary

某些查询条件阻止使用内存中的临时 table,在这种情况下,服务器将使用磁盘上的 table 代替:

  • table 格中存在BLOBTEXT列。这包括具有字符串值的用户定义变量,因为它们分别被视为BLOB列或TEXT列,具体取决于它们的值是二进制字符串还是非二进制字符串。

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

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

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

这些条件使UNION可以在没有临时 table 的情况下进行评估:

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

  • 没有全局ORDER BY子句。

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

内部临时 table 存储引擎

内部临时 table 可以保存在内存中,并由MEMORY存储引擎处理,或者由InnoDBMyISAM存储引擎存储在磁盘上。

如果内部临时 table 被创建为内存 table,但又太大了,MySQL 会自动将其转换为磁盘 table。内存中临时 table 的最大大小由tmp_table_sizemax_heap_table_size值定义,以较小者为准。这与使用CREATE TABLE显式创建的MEMORYtable 不同。对于此类 table,只有max_heap_table_size变量确定 table 可以增长到多大,并且不转换为磁盘格式。

internal_tmp_disk_storage_engine变量定义服务器用来 Management 磁盘内部临时 table 的存储引擎。允许的值为INNODB(默认值)和MYISAM

Note

使用internal_tmp_disk_storage_engine=INNODB时,生成超过InnoDB 行或列限制的磁盘内部临时 table 的查询将返回行大小太大或列过多的错误。解决方法是将internal_tmp_disk_storage_engine设置为MYISAM

当在内存或磁盘中创建内部临时 table 时,服务器将使Created_tmp_tables值递增。在磁盘上创建内部临时 table 时,服务器将使Created_tmp_disk_tables值递增。如果在磁盘上创建了太多内部临时 table,请考虑增加tmp_table_sizemax_heap_table_size设置。

内部临时 table 存储格式

内存中的临时 table 由MEMORY存储引擎 Management,该引擎使用固定长度的行格式。 VARCHARVARBINARY列值被填充为最大列长度,实际上将它们存储为CHARBINARY列。

磁盘上的临时 table 由InnoDBMyISAM存储引擎(取决于internal_tmp_disk_storage_engine设置)Management。两个引擎都使用动态宽度行格式存储临时 table。列仅占用所需的存储空间,与使用固定长度行的磁盘 table 相比,这减少了磁盘 I/O,空间需求和处理时间。

对于最初在内存中创建内部临时 table 然后将其转换为磁盘上 table 的语句,跳过转换步骤并在磁盘上开始创建 table 可能会获得更好的性能。 big_tables变量可用于强制内部临时 table 进行磁盘存储。