1.内存表,指的是使用 Memory 引擎的表,建表语法是 create table … engine=memory。这种表的数据都保存在内存里,系统重启的时候会被清空,但是表 结构还在。
2.临时表,可以使用各种引擎类型 。如果是使用 InnoDB 引擎或者 MyISAM 引擎的临 时表,写数据的时候是写到磁盘上的。当然,临时表也可以使用 Memory 引擎
因此临时表不等于内存表。
建表语法是 create temporary table …。
1.一个临时表只能被创建它的 session 访问,对其他线程不可见。
2.临时表可以与普通表同名。
3.session A 内有同名的临时表和普通表的时候,show create 语句,以及增删改查语句访
问的是临时表。
4.show tables 命令不显示临时表。
临时表只能被创建它的 session 访问,所以在这个 session 结束的时候,会自动删除 临时表
优点:
1.临时表只能被创建它的 session 访问,所以在这个 session 结束的时候,会自动删除 临时表
2.不需要担心数据删除问题。如果使用普通表,在流程执行过程中客户端发生了异常断 开,或者数据库发生异常重启,还需要专门来清理中间过程中生成的数据表。而临时表 由于会自动回收,所以不需要这个额外的操作。
临时表的应用
由于不用担心线程之间的重名冲突,临时表经常会被用在复杂查询的优化过程中。其中,分
库分表系统的跨库查询就是一个典型的使用场景。
把各个分库拿到的数据,汇总到一个 MySQL 实例的一个表中,然后在 这个汇总实例上做逻辑操作
在汇总库上创建一个临时表,把分库执行的结果插入到临时表中;
临时表上的操作不会被写入到binlog中,如果binglog是row格式。
临时表一般用于处理比较复杂的计算逻辑。由于临时表是每个线程自己可见
的,所以不需要考虑多个线程执行同一个处理逻辑时,临时表的重名问题。在线程退出的时
候,临时表也能自动删除,省去了收尾和异常处理的工作。
在 binlog_format='row’的时候,临时表的操作不记录到 binlog 。
但是如果在程序中,用的是连接 池中的连接来操作的,而这些连接不会释放,和数据库保持长连接。这样使用临时表会有问题,
因此需要手动删除,用完即删。
37.内存临时表
比如说union
先将第一个查询的结果存到内存临时表中,然后将第二个查询,依次查询 ,依次放。
最后将临时表中按行取出数据,并删除临时表。 这里的临时表 除了暂存数据,
还利用了临时表上的建立的唯一约束,实现了union的语义。
如果把上面这个语句中的 union 改成 union all 的话,就没有了“去重”的 语义,
也就不需要临时表了,直接合并结果集返回。
groupby
也会用到临时表。
1.创建内存临时表
2.扫描查询的表 将数据放到临时表
3.在临时表中根据 group by 的字段排序,将得到的结果集返回给客户端。
groupby的语义是 统计不同值出现的个数。
如果值无序,就需要使用这个临时表,进行辅助。
但是如果值是有序的,那么只需要挨个遍历一次就可以统计出结果。
因此在group by 的字段加上索引,就可以优化掉这个临时表和排序。
- 如果语句执行过程可以一边读数据,一边直接得到结果,是不需要额外内存的,否则就 需要额外的内存,来保存中间结果;
- join_buffer 是无序数组,sort_buffer 是有序数组,临时表是二维表结构;
- 如果执行逻辑需要用到二维表特性,就会优先考虑使用临时表。 union 需要用到唯一索引约束, group by 还需要用到另外一个字段来存累积计数。
4.如果对 group by 语句的结果没有排序要求,要在语句后面加 order by null;
5.尽量让 group by 过程用上表的索引,确认方法是 explain 结果里没有 Using temporary 和 Using filesort;
6.如果 group by 需要统计的数据量不大,尽量只使用内存临时表;也可以通过适当调大
tmp_table_size 参数,来避免用到磁盘临时表;
7.如果数据量实在太大,使用 SQL_BIG_RESULT 这个提示,来告诉优化器直接使用排序算
法得到 group by 的结果。