临时表不等于内存表。
临时表是 session 级别,不同 session 互不可见,可与普通表同名,增重名时删改查用的是临时表。
临时表和 内存表 的概念
-
内存表,指的是使用 Memory 引擎的表,建表语法是
create table … engine=memory。这种表的数据都保存在内存里,系统重启的时候会被清空,但是表结构还在。除了这两个特性看上去比较“奇怪”外,从其他的特征上看,它就是一个正常的表。 -
而临时表,可以使用各种引擎类型。如果是使用 InnoDB 引擎或者 MyISAM 引擎的临时表,写数据的时候是写到磁盘上的。当然,临时表也可以使用 Memory 引擎。
临时表的特性
临时表在使用上有以下几个特点:
- 建表语法是
create temporary table …。 - 一个临时表只能被创建它的 session 访问,对其他线程不可见。
- 临时表可以与普通表同名。
- session A 内有同名的临时表和普通表的时候,show create 语句,以及增删改查语句访问的是临时表。
- show tables 命令不显示临时表。
由于临时表只能被创建它的 session 访问,所以在这个 session 结束的时候,会自动删除临时表。也正是由于这个特性,临时表就特别适合 join 优化这种场景。为什么呢?
原因主要包括以下两个方面:
- 不同 session 的临时表是可以重名的,如果有多个 session 同时执行 join 优化,不需要担心表名重复导致建表失败的问题。
- 不需要担心数据删除问题。如果使用普通表,在流程执行过程中客户端发生了异常断开,或者数据库发生异常重启,还需要专门来清理中间过程中生成的数据表。而临时表由于会自动回收,所以不需要这个额外的操作。
补充:重启以后 MySQL 会扫描临时目录,把表都删掉,以避免历史临时表因为特殊原因导致未删除。
临时表的应用
由于不用担心线程之间的重名冲突,临时表经常会被用在复杂查询的优化过程中。其中,分库分表系统的跨库查询就是一个典型的使用场景。
一般分库分表的场景,就是要把一个逻辑上的大表分散到不同的数据库实例上。比如。将一个大表 ht,按照字段 f,拆分成 1024 个分表,然后分布到 32 个数据库实例上。如下图所示:

一般情况下,这种分库分表系统都有一个中间层 proxy。不过,也有一些方案会让客户端直接连接数据库,也就是没有 proxy 这一层。
在这个架构中,分区 key 的选择是以“减少跨库和跨表查询”为依据的。如果大部分的语句都会包含 f 的等值条件,那么就要用 f 做分区键。这样,在 proxy 这一层解析完 SQL 语句以后,就能确定将这条语句路由到哪个分表做查询。
比如下面这条语句:
select v from ht where f=N;这时,我们就可以通过分表规则(比如,N%1024) 来确认需要的数据被放在了哪个分表上。这种语句只需要访问一个分表,是分库分表方案最欢迎的语句形式了。
但是,如果这个表上还有另外一个索引 k,并且查询语句是这样的:
select v from ht where k >= M order by t_modified desc limit 100;这时候,由于查询条件里面没有用到分区字段 f,只能到所有的分区中去查找满足条件的所有行,然后统一做 order by 的操作。这种情况下,有两种比较常用的思路。
第一种思路是,在 proxy 层的进程代码中实现排序。
这种方式的优势是处理速度快,拿到分库的数据以后,直接在内存中参与计算。不过,这个方案的缺点也比较明显:
- 需要的开发工作量比较大。我们举例的这条语句还算是比较简单的,如果涉及到复杂的操作,比如 group by,甚至 join 这样的操作,对中间层的开发能力要求比较高;
- 对 proxy 端的压力比较大,尤其是很容易出现内存不够用和 CPU 瓶颈的问题。
另一种思路就是,把各个分库拿到的数据,汇总到一个 MySQL 实例的一个表中,然后在这个汇总实例上做逻辑操作。
比如上面这条语句,执行流程可以类似这样:
- 在汇总库上创建一个临时表 temp_ht,表里包含三个字段 v、k、t_modified;
- 在各个分库上执行
select v,k,t_modified from ht_x where k >= M order by t_modified desc limit 100; - 把分库执行的结果插入到 temp_ht 表中;
- 执行下面语句得到结果。
select v from temp_ht order by t_modified desc limit 100;
这个过程对应的流程图如下所示:

在实践中,我们往往会发现每个分库的计算量都不饱和,所以会直接把临时表 temp_ht 放到 32 个分库中的某一个上。这时的查询逻辑与图 3 类似,你可以自己再思考一下具体的流程。