MySQL 临时表、内存表的使用

MySQL 临时表、内存表的使用

一、临时表:

临时表的创建语法:create temporary table

1.临时表有哪些特点?

  1. 一个临时表只能被创建它的session访问,对其他线程不可见。

    SessionA创建临时表t,SessionB是看不见的;

  2. 临时表可以与普通表同名。

  3. SessionA内有同名的临时表和普通表的时候,show create 语句,以及增删改查语句访问的是临时表。

  4. show create 命令不显示临时表。

  5. 由于临时表只能被创建它的Session访问,所以在这个Session结束的时候,会自动删除临时表。

2.临时表适合优化join场景条件?

  1. 不同的Session临时表是可以重名的,如果有多个Session同时执行join优化,不需要担心表名重复导致建表失败的问题。

  2. 不需要担心数据删除的问题。

    如果普通表,在流程执行过程中客户端发生异常断开,或者数据发生重启,需要专门来清理中间过程中生成的数据表。

    而临时表由于会自动回收,所以不需要额外的操作;

3.为什么临时表可以重名?

create temporary table temp_t(id int primary key)engine=innodb;

MySQL要给InnoDB表创建一个frm文件保存表结构定义,还要有地方保存表数据。

  1. 这个frm文件放在临时文件目录下,文件名的后缀是.frm,前缀是"#sql{进程 id}_ {线程id} _ 序列号"。

    可使用select @@ tmpdir 命令,来显示实例的临时文件目录;

  2. 所以SessionA和SessionB创建的临时表,在磁盘上的文件不会重名。

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

  1. 一个普通表的 table _ def _ key的值,是由"库名 + 表名" 得到,所以要在同一个库下创建两个同名的普通表,创建第二个表过程中就会发现table _def _ key已经存在了。
  2. 而对于临时表,table _ def _key 在"库名 + 表名" 基础上,又加了"server _ id + thread _ id"

简单理解,SessionA、SessionB创建两个临时表t1,它们的table _ def _key不同,磁盘文件名也不同,因此可以并存;

4.临时表主备复制:

  1. binlog _format=row 设置row 模式,临时表不会同步到备库中;(不会记录到binlog日志里)
  2. binlog_format=statment/mixed 设置statement 模式,会同步到备库中;(记录到binlog日志里)

5.临时表使用场景:

  1. 数据一边查询,一边直接得到结果,不需要额外内存;
  2. join_buffer,是无序数组(单字段、可以重复);
  3. sort_buffer,有序数组,内部临时表是二维结构;
  4. 用到二维表的特性需要用到内部临时表,比如distinct、group by;

6.临时表优化:

  1. group by 字段加索引;
  2. 扩大临时表内存大小;
  3. 如果数据量比较大,直接使用磁盘临时表;
  4. 如果分组之后,不需要排序,手工order by null;

二、内存表:

1.内存表的优势:

内存表的优势是速度快,其中的一个原因就是Memory引擎支持hash索引。内存表所有的数据都保存在内存,而内存的读写速度总是比磁盘快。

2.内存表的劣势:

  1. 锁粒度问题;
  2. 数据持久化的问题;

3.内存表的锁:

内存表不支持行锁,仅支持表锁,所以一张表只要有更新,就会堵住其他所有在这个表上的读写操作

跟行锁比起来,表锁对并发访问的支持不够好,所以,内存表的锁粒度问题,决定了它在处理并发事务的时候,性能不会太好;

4.数据持久性的问题:

数据放在内存中,是内存表的优势,但也是劣势。因为数据库重启的时候,所有内存表会被清空。但是在高可用架构下,内存表的这个特点就跟bug一样。

使用内存表,在高可用架构上的问题:

业务正常访问主库;
备库硬件升级、备库重启、内存表t1内容被清空;
备库重启后,客户端发送一条update语句,修改表t1的数据行,这时备用线程就会报错"找不到更新的行"

会导致主备同步停止,这时主备切换的话,客户端会看到,表t1的数据"丢失";

为什么内存表不适合在生产环境上作为普通数据表使用?

  1. 如果你的表更新量大,那么并发是一个很重要的参考指标,InnoDB支持行锁,并发度比内存表好;
  2. 能放到内存表的数据库都不大。如果考虑读的性能,一个读QPS很高并且数据量不大的表,即使是使用InnoDB,数据也都是会缓存在InnoDB Buffer Pool 里。因此InnoDB读性能也不会差;

建议把普通内存表都用InnoDB表来代替;

三、临时表和内存表的区别:

1.内存临时表比内存表的优势:

  1. 临时表不会被其他线程访问,没有并发性的问题;

  2. 临时表重启后也需要删除的,清空数据这个问题不存在;

  3. 备库的临时表也不影响主库的用户线程;

    使用内存临时表的速度都比使用InnoDB临时表要更快一些;

2.临时表合内存表区别?

  1. 内存表指的是使用Memory引擎的表,数据保存到内存里,重启会丢失数据,但是表结构还在;
  2. 临时表可以使用各种引擎类型。如果是使用InnoDB引擎或者是MyISAM引擎的临时表,数据写在磁盘上;
  3. 临时表也可以使用Memory引擎

四、InnoDB和Memory引擎数据组织方式不同:

InnoDB引擎把数据放在主键索引上,其他索引上保存的是主键id,这种方式,我们称索引组织表

Memory引擎采用的是把数据单独存放,索引上保存数据位置的数据组织形式,我们称堆组织表

五、InnoDB和Memory典型不同:

  1. InnoDB表数据总是有序存放的,而内存表的数据就是按照写入顺序存放的;
  2. 当数据文件有空洞的时候,InnoDB表插入新的数据时候,为了保证数据有序性,只能在固定的位置写入新值,而内存表找到空位就可以插入新值;
  3. 数据位置发生变化的时候,InnoDB表仅需要修改主键索引,而内存表需要修改所有索引;
  4. InnoDB表用主键索引查询时需要走一次索引查找,用普通索引查询的时候,需要走两次索引查询。而内存表没有这个区别,所有索引的"地位"都是相同的;
  5. InnoDB支持变成数据类型,不同记录的长度可能不同;内存表不支持Blob和Text字段,并且定义了varchar(N),实际也当作char(N),也就是固定长度字符串来存储,因此内存表的每行数据长度相同;
发布了147 篇原创文章 · 获赞 170 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/Fe_cow/article/details/103272466