天天看点

[MySQL5.7] 5.7版本针对临时表的优化

尽量临时表在实际在线场景中很少会去显式使用,但在某些运维场景还是需要到的,在mysql5.7中,专门针对临时表做了些优化;大概扫了下代码,把一些要点及关键函数记录下。

#独立的tmp表空间,默认在data目录下建立一个命名为ibtmp1的临时表表空间;对于非压缩临时表,表空间内容存放到ibtmp1下面;对于压缩表,依然会为其在tmp目录下建立ibd文件;

#server启动时会删除之前的ibtmp文件并重建(函数srv_open_tmp_tablespace)

#临时表空间使用全局变量srv_tmp_space(5.7里所有对表空间的管理的代码被重构成类tablespace)

#无需为临时表记录redo log,因为临时表不做crash recovery;因此在针对临时表的大量操作直接disable redo (dict_disable_redo_if_temporary)

#临时表专用的回滚段,回滚段同样被记录到临时表空间ibtmp1下面(trx_sys_create_noredo_rsegs); 降低和其他实体表的undo log存储产生竞争

尽管临时表无需做crash recovery,但依然要为其创建undo log表空间,因为可能在事务执行的过程中,需要回滚到某个savepoint;

临时表的undo log无需写redo (实体表的undo是需要写redo的)

128个回滚段中的32个回滚段(srv_tmp_undo_logs)专门预留给临时表操作(回滚段trx_rsegs_t被分为两类:m_redo及m_noredo)

针对purge操作,也做了修改,采用一个优先队列来进行操作(具体见函数trxundorsegsiterator::set_next(),  purge_sys->purge_queue, 在函数trx_purge_rseg_get_next_history_log中往队列加undo,创建临时表回滚段调用trx_sys_create_noredo_rsegs)

其他相关函数:trx_sysf_rseg_find_free,查找回滚段(get_next_redo_rseg及get_next_noredo_rseg, trx_assign_rseg_low)

对undo的修改详细见该patch: http://bazaar.launchpad.net/~mysql/mysql-server/5.7/revision/5832

#临时表的定义可以存放在内存,无需持久化到磁盘;

无需将临时表的元数据信息写入到系统表(对于临时表,create_table_def直接调用dict_build_tablespace && dict_table_add_to_cache

创建索引时同样区分对待(row_create_index_for_mysql)

其他相关函数:dict_build_index_def,dict_create_index_tree,dict_recreate_index_tree(include/dict0crea.h),这些函数用于对表元数据进行操作而无需更新系统表

#降低对临时表的锁约束,因为临时表只对当前client可见;

例如无需对更新临时表的二级索引页设置trx id, 不做可见性判断(lock_clust_rec_cons_read_sees, lock_sec_rec_cons_read_sees, lock_sec_rec_read_check_and_lock),不会去加innodb层表锁 (lock_table)

甚至对临时表而言记录锁也是多余的。

#避免对临时表使用change buffer.  另外在ibtmp表空间中的临时表也不为其分配ibuf  bitmap page(fsp_fill_free_list)

#增加了一个新的information schema表innodb_temp_table_info来显示临时表信息

root@test 12:41:54>create temporary table t1 (a int);

query ok, 0 rows affected (0.00 sec)

root@test 12:42:17>create temporary table t2 (a int) row_format=compressed;

root@test 12:42:26>select * from information_schema.innodb_temp_table_info;

+———-+————–+——–+——-+———————-+—————+

| table_id | name         | n_cols | space | per_table_tablespace | is_compressed |

|       63 | #sql7e20_7_1 |      4 |    65 | true                 | true          |

|       62 | #sql7e20_7_0 |      4 |    62 | false                | false         |

2 rows in set (0.00 sec)

代码的修改包含在以下几个patch中:

http://bazaar.launchpad.net/~mysql/mysql-server/5.7/revision/5150

http://bazaar.launchpad.net/~mysql/mysql-server/5.7/revision/5456

http://bazaar.launchpad.net/~mysql/mysql-server/5.7/revision/5832

创建ibtmp的diff包含在另外一个大diff中(尼玛完全没法看啊。。。)

http://bazaar.launchpad.net/~mysql/mysql-server/5.7/revision/5112

官方博客上的性能数据:

create/drop临时表的性能:

[MySQL5.7] 5.7版本针对临时表的优化

临时表的dml性能:

[MySQL5.7] 5.7版本针对临时表的优化

——————–

ref:

官方博客的介绍绍:https://blogs.oracle.com/mysqlinnodb/entry/https_blogs_oracle_com_mysqlinnodb

mysql5.7.3源代码

 ############

updated @ 2014-11-27,补充下官方相关总结(当前版本:5.7.5)

innodb temporary table performance