勘误:临时表就是内存表。但是,这两个概念可是完全不同的。
内存表 | 指的是使用 Memory 引擎的表,建表语法是 create table … engine=memory。这种表的数据都保存在内存里,系统重启的时候会被清空,但是表结构还在。除了这两个特性看上去比较“奇怪”外,从其他的特征上看,它就是一个正常的表。 |
---|---|
临时表 | 临时表,可以使用各种引擎类型 。如果是使用 InnoDB 引擎或者 MyISAM 引擎的临时表,写数据的时候是写到磁盘上的。当然,临时表也可以使用 Memory 引擎。 |
临时表有哪些特征?
- 建表语法是 create temporary table …。
- 一个临时表只能被创建它的 session 访问,对其他线程不可见。所以,图中 session A 创建的临时表 t,对于 session B 就是不可见的。
- 临时表可以与普通表同名。
- session A 内有同名的临时表和普通表的时候,show create 语句,以及增删改查语句访问的是临时表。
- show tables 命令不显示临时表。
它适合哪些场景?
由于不用担心线程之间的重名冲突,临时表经常会被用在复杂查询的优化过程中。
- 分库分表系统的跨库查询就是一个典型的使用场景。
为什么临时表可以重名?
- 物理存储:在临时文件目录下,文件名的后缀是.frm,前缀是“#sql{进程 id}{线程 id} 序列号”
- 内存:临时表,table_def_key 在“库名 + 表名”基础上,又加入了“server_id+thread_id”。
在实现上,每个线程都维护了自己的临时表链表。这样每次 session 内操作表的时候,先遍历链表,检查是否有这个名字的临时表,如果有就优先操作临时表,如果没有再操作普通表;在 session 结束的时候,对链表里的每个临时表,执行 “DROP TEMPORARY TABLE + 表名”操作。这时候你会发现,binlog 中也记录了 DROP TEMPORARY TABLE 这条命令。
临时表只在线程内自己可以访问,为什么需要写到 binlog 里面?
临时表和主备复制
如果当前的 binlog_format=row,那么跟临时表有关的语句,就不会记录到 binlog 里。也就是说,只在 binlog_format=statment/mixed 的时候,binlog 中才会记录临时表的操作。
是用户自己创建的 ,也可以称为用户临时表。
与它相对应的,就是内部临时表,MySQL 什么时候会使用内部临时表呢?
- union
- group by
内存临时表的大小是有限制的,参数 tmp_table_size 就是控制这个内存大小的,默认是 16M。超过之后会把内存临时表转成磁盘临时表,磁盘临时表默认使用的引擎是 InnoDB。
使用 left join 时,左边的表不一定是驱动表。这样看来,如果需要 left join 的语义,就不能把被驱动表的字段放在 where 条件里面做等值判断或不等值判断,必须都写在 on 里面。