临时表的一些特性:

1、创建语法:create temporary table

2、只有创建该表的session才可以访问,其他线程无法访问

3、临时表可以与普通表重名

4、session中有同名的临时表和普通表时,操作的都是临时表

临时表应用

在分库分表的场景下,我们现在假设某一个大表ht 按照字段f分为了1024个表,分布在32个数据库上。如下图所示:

image-20230424170242139

这种设计下,如果我们执行如下sql:

1
select v from ht where f = N;

因为该sql使用了分表的字段f,那么我们就可以直接找到数据所在的表。

但是如果是如下sql:

1
select v from ht where k >= M order by t_modified desc limit 100;

该sql没有使用到分表的字段f,那么只能到所有的分区中去查找满足条件的所有行,然后统一做order by 的操作。

这种情况下,有两种方法:

1、把所有的数据全部查到,然后交给代理层去做排序。这种方法的优点是MySQL查询会很快,但是需要代理层多做额外的处理。

2、把各个分库拿到的数据,汇总到一个MySQL实例的一个表中,然后在这个汇总实例上做逻辑操作。流程如下图:

image-20230424171857340

为什么临时表可以重名?

MySQL维护数据表,除了物理上要有文件外,内存里面也有一套机制区别不同的表,每个表都对应一个table_def_key。

  • 一个普通表的table_def_key的值是由“库名+表名”得到的,所以如果你要在同一个库下创建两个同名的普通表,创建第二个表的过程中就会发现table_def_key已经存在了。
  • 而对于临时表,table_def_key在“库名+表名”基础上,又加入了“server_id+thread_id”。

也就是说,session A和sessionB创建的两个临时表t1,它们的table_def_key不同,磁盘文件名也不同,因此可以并存。

在实现上,每个线程都维护了自己的临时表链表。这样每次session内操作表的时候,先遍历链表,检查是否有这个名字的临时表,如果有就优先操作临时表,如果没有再操作普通表;在session结束的时候,对链表里的每个临时表,执行 “DROP TEMPORARY TABLE +表名”操作。