information_schema有何用?

  • 通过I_S获取mysql的一些元数据信息
  • 获取表的数据文件、索引文件的大小、碎片情况、表行数、自增列增长情况等
  • 获取正在运行的事务有那些,是否有阻塞等
  • 获取当前mysql的连接processlist等等

mysql8.0 之前的查询方式

会在查询information_schema 某个表时创建临时表

  • 来自文件的元数据,扫描文件系统获取FRM文件的表定义
  • 存储引擎的详细信息,例如动态表统计信息
  • 来自MySQL服务器中全局数据结构的数据

在表的数量很多时,每次查询I_S会从文件系统中读取每个单独的FRM文件,使用更多的CPU周期来打开表并准备相关的内存数据结构

mysql8.0 开始的查询方式

  • 引入了基于InnoDB的本地数据字典表
  • 表中不在有FRM表定义文件
  • 所有数据库表的元数据都存储在事务数据字典表中
  • I_S中表被设计为数据字典表上的VIEW(有些还是临时表0_0)

消除了以下成本

查询INFORMATION_SCHEMA时创建的临时表

扫描文件系统目录以查找FRM文件

改进

利用MySQL优化器的全部功能,使用数据字典表上的索引来更好的查询

mysql5.7中表文件

ll test*

Jul 10 10:52 testse.frm

Jul 10 10:52 testse.ibd

mysql8.0中表文件

ll test*

Jul 10 10:25 testse.ibd

mysql5.7 和mysql8.0 I_S 中tables 表的存在方式

  1. mysql5.7.22
  2. show create table information_schema.tables\G
  3. *************************** 1. row ***************************
  4. Table: TABLES
  5. Create Table: CREATE TEMPORARY TABLE `TABLES` (
  6. `TABLE_CATALOG` varchar(512) NOT NULL DEFAULT '',
  7. `TABLE_SCHEMA` varchar(64) NOT NULL DEFAULT '',
  8. `TABLE_NAME` varchar(64) NOT NULL DEFAULT '',
  9. `TABLE_TYPE` varchar(64) NOT NULL DEFAULT '',
  10. `ENGINE` varchar(64) DEFAULT NULL,
  11. mysql8.0.15
  12. show create table information_schema.tables\G
  13. *************************** 1. row ***************************
  14. View: TABLES
  15. Create View: CREATE ALGORITHM=UNDEFINED DEFINER=`mysql.infoschema`@`localhost` SQL SECURITY DEFINER VIEW `
  • mysql5.7 中I_S中tables表是以临时表的形式存在的(查询该表就会创建临时表,创建的临时表过多,可能会导致mysql占用的内存暴涨,出现OOM)
  • mysql8.0 中I_S中tables表以视图的形式存在(查询该视图,不会创建临时表,会使用到视图中表的索引)

mysql5.7中获取表大小情况

  1. SELECT table_name, CONCAT(FORMAT(data_length / 1024 / 1024, 2), 'M') AS dbdata_size, CONCAT(FORMAT(index_length / 1024 / 1024, 2), 'M') AS dbindex_size, CONCAT( FORMAT((data_length + index_length) / 1024 / 1024 / 1024,2), 'G') AS `db_size(G)`, AVG_ROW_LENGTH, table_rows, update_time FROM information_schema.tables WHERE table_schema = 'test' AND table_name = 'testse';
  2. +------------+-------------+--------------+------------+----------------+------------+---------------------+
  3. | table_name | dbdata_size | dbindex_size | db_size(G) | AVG_ROW_LENGTH | table_rows | update_time |
  4. +------------+-------------+--------------+------------+----------------+------------+---------------------+
  5. | testse | 0.02M | 0.02M | 0.00G | 862 | 19 | 2019-07-10 10:52:02 |
  6. +------------+-------------+--------------+------------+----------------+------------+---------------------+
  7. 执行计划中出现了where,未用到索引(存储引擎检索数据后,server层进行过滤)
  8. desc SELECT table_name, CONCAT(FORMAT(data_length / 1024 / 1024, 2), 'M') AS dbdata_size, CONCAT(FORMAT(index_length / 1024 / 1024, 2), 'M') AS dbindex_size, CONCAT( FORMAT(data_length + index_length / 1024 / 1024 / 1024, 2 ), 'G') AS `db_size(G)`, AVG_ROW_LENGTH, table_rows, update_time FROM information_schema.tables WHERE table_schema = 'test' AND table_name = 'testse';
  9. +----+-------------+--------+------------+------+---------------+-------------------------+---------+------+------+----------+---------------------------------------------------+
  10. | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
  11. +----+-------------+--------+------------+------+---------------+-------------------------+---------+------+------+----------+---------------------------------------------------+
  12. | 1 | SIMPLE | tables | NULL | ALL | NULL | TABLE_SCHEMA,TABLE_NAME | NULL | NULL | NULL | NULL | Using where; Open_full_table; Scanned 0 databases |
  13. +----+-------------+--------+------------+------+---------------+-------------------------+---------+------+------+----------+---------------------------------------------------+

mysql8.0中获取表大小情况

  1. SELECT table_name, CONCAT(FORMAT(data_length / 1024 / 1024, 2), 'M') AS dbdata_size, CONCAT(FORMAT(index_length / 1024 / 1024, 2), 'M') AS dbindex_size, CONCAT( FORMAT((data_length + index_length) / 1024 / 1024 / 1024,2), 'G') AS `db_size(G)`, AVG_ROW_LENGTH, table_rows, update_time FROM information_schema.tables WHERE table_schema = 'test' AND table_name = 'testse';
  2. +------------+-------------+--------------+------------+----------------+------------+---------------------+
  3. | TABLE_NAME | dbdata_size | dbindex_size | db_size(G) | AVG_ROW_LENGTH | TABLE_ROWS | UPDATE_TIME |
  4. +------------+-------------+--------------+------------+----------------+------------+---------------------+
  5. | testse | 0.02M | 0.02M | 0.00G | 862 | 19 | 2019-07-10 10:25:16 |
  6. +------------+-------------+--------------+------------+----------------+------------+---------------------+
  7. 能使用到数据字典表的索引
  8. desc SELECT table_name, CONCAT(FORMAT(data_length / 1024 / 1024, 2), 'M') AS dbdata_size, CONCAT(FORMAT(index_length / 1024 / 1024, 2), 'M') AS dbindex_size, CONCAT( FORMAT((data_length + index_length) / 1024 / 1024 / 1024,2), 'G') AS `db_size(G)`, AVG_ROW_LENGTH, table_rows, update_time FROM information_schema.tables WHERE table_schema = 'test' AND table_name = 'testse';
  9. +----+-------------+-------+------------+--------+--------------------+------------+---------+-------------------------+------+----------+-------------+
  10. | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
  11. +----+-------------+-------+------------+--------+--------------------+------------+---------+-------------------------+------+----------+-------------+
  12. | 1 | SIMPLE | cat | NULL | index | PRIMARY | name | 194 | NULL | 1 | 100.00 | Using index |
  13. | 1 | SIMPLE | sch | NULL | eq_ref | PRIMARY,catalog_id | catalog_id | 202 | mysql.cat.id,const | 1 | 100.00 | Using index |
  14. | 1 | SIMPLE | tbl | NULL | eq_ref | schema_id | schema_id | 202 | mysql.sch.id,const | 1 | 100.00 | Using where |
  15. | 1 | SIMPLE | stat | NULL | const | PRIMARY | PRIMARY | 388 | const,const | 1 | 100.00 | NULL |
  16. | 1 | SIMPLE | ts | NULL | eq_ref | PRIMARY | PRIMARY | 8 | mysql.tbl.tablespace_id | 1 | 100.00 | NULL |
  17. | 1 | SIMPLE | col | NULL | eq_ref | PRIMARY | PRIMARY | 8 | mysql.tbl.collation_id | 1 | 100.00 | Using index |
  18. +----+-------------+-------+------------+--------+--------------------+------------+---------+-------------------------+------+----------+-------------+

测试5.7和8.0不同版本访问I_S库的性能

机器

  1. cat /etc/redhat-release | xargs echo '版本 ' && dmidecode -s system-product-name | xargs echo '是否虚拟化 ' && cat /proc/cpuinfo |grep "processor"|wc -l | xargs echo 'cpu核数 '
  2. 版本 CentOS Linux release 7.5.1804 (Core)
  3. 是否虚拟化 KVM
  4. cpu核数 4

1、分别在mysql5.7和mysql8.0 中创建5个库,每个库中30个表(共1500个表),每个表记录数为10000

  1. user=admin
  2. passwd=admin
  3. port=57222
  4. host=127.0.0.1
  5. #创建5个库,分别在每个库中创建30个表
  6. for i in {1..5};do
  7. mysql -u$user -p$passwd -P$port -h$host<<EOF
  8. create database if not exists test_${i};
  9. EOF
  10. sysbench /usr/local/share/sysbench/oltp_read_write.lua --mysql_storage_engine=innodb --table-size=10000 --tables=30 --mysql-db=test_${i} --mysql-user=$user --mysql-password=$passwd --mysql-port=$port --mysql-host=$host --threads=8 --time=10 --report-interval=1 --events=0 --db-driver=mysql prepare
  11. done;

2、自定义访问I_S.tables表的sysbench脚本

cat tests/mytest.lua

  1. require("oltp_common")
  2. function thread_init(thread_id)
  3. drv=sysbench.sql.driver()
  4. con=drv:connect()
  5. end
  6. local function get_rand_db()
  7. return sysbench.rand.uniform(1, 5)
  8. end
  9. function event(thread_id)
  10. local vid1
  11. local dbprefix
  12. vid1=get_rand_db()
  13. dbprefix = "test_"
  14. -- 生成5db中的随机一个db,如 test_1 ,test_5
  15. -- vid2=string.format("'%s%s'",test_,vid1)
  16. vid2="'" .. dbprefix .. vid1 .. "'"
  17. con:query("SELECT table_name, CONCAT(FORMAT(data_length / 1024 / 1024, 2), 'M') AS dbdata_size, CONCAT(FORMAT(index_length / 1024 / 1024, 2), 'M') AS dbindex_size, CONCAT( FORMAT((data_length + index_length) / 1024 / 1024 / 1024,2), 'G') AS `db_size(G)`, AVG_ROW_LENGTH, table_rows, update_time FROM information_schema.tables WHERE table_schema =" .. vid2)
  18. end
  19. function thread_done()
  20. con:disconnect()
  21. end

3、脚本通过sysbench测试访问I_S.tables的qps

cat test_I_S_access.sh

  1. user=admin
  2. passwd=admin
  3. host=127.0.0.1
  4. #输入mysql端口参数
  5. port=$1
  6. # port=8015
  7. #输入sysbench测试时间参数多少秒
  8. run_time=$2
  9. function get_create_tmp_tables(){
  10. mysql -u$user -p$passwd -P$port -h$host<<EOF
  11. select @@version as 'mysql version';
  12. show global status like '%tmp_table%';
  13. EOF
  14. } 2>/dev/null
  15. function begin_test(){
  16. cd /usr/local/share/sysbench
  17. sysbench ./tests/mytest.lua --mysql-db=test_1 --mysql-host=$host --mysql-port=$port --mysql-user=$user --mysql-password=$passwd --threads=40 --report-interval=10 --rand-type=uniform --time=$run_time run
  18. }
  19. service mysqld${port} restart
  20. get_create_tmp_tables
  21. begin_test
  22. get_create_tmp_tables

4、mysql5.7和mysql8.0 主要配置

  1. mysql5.7.22
  2. 5.7.22-log
  3. innodb_buffer_pool_size 128M
  4. innodb_log_buffer_size 64M
  5. innodb_log_file_size 48M
  6. binlog_format ROW
  7. innodb_flush_log_at_trx_commit 1
  8. sync_binlog 1
  9. mysql8.0.15
  10. 8.0.15
  11. innodb_buffer_pool_size 128M
  12. innodb_log_buffer_size 64M
  13. innodb_log_file_size 48M
  14. binlog_format ROW
  15. innodb_flush_log_at_trx_commit 1
  16. sync_binlog 1

5、mysql5.7开启测试

bash test_I_S_acess.sh 57222 60

  1. Shutting down MySQL.. SUCCESS!
  2. Starting MySQL.. SUCCESS!
  3. mysql version
  4. 5.7.22-log
  5. Variable_name Value
  6. Created_tmp_tables 1
  7. sysbench 1.1.0 (using bundled LuaJIT 2.1.0-beta3)
  8. Running the test with following options:
  9. Number of threads: 40
  10. Report intermediate results every 10 second(s)
  11. Initializing random number generator from current time
  12. Initializing worker threads...
  13. Threads started!
  14. [ 10s ] thds: 40 tps: 4765.73 qps: 4765.73 (r/w/o: 4765.73/0.00/0.00) lat (ms,95%): 18.95 err/s: 0.00 reconn/s: 0.00
  15. [ 20s ] thds: 40 tps: 5409.00 qps: 5409.00 (r/w/o: 5409.00/0.00/0.00) lat (ms,95%): 17.95 err/s: 0.00 reconn/s: 0.00
  16. [ 30s ] thds: 40 tps: 5154.45 qps: 5154.45 (r/w/o: 5154.45/0.00/0.00) lat (ms,95%): 18.61 err/s: 0.00 reconn/s: 0.00
  17. [ 40s ] thds: 40 tps: 5383.50 qps: 5383.50 (r/w/o: 5383.50/0.00/0.00) lat (ms,95%): 17.63 err/s: 0.00 reconn/s: 0.00
  18. [ 50s ] thds: 40 tps: 5456.11 qps: 5456.11 (r/w/o: 5456.11/0.00/0.00) lat (ms,95%): 17.63 err/s: 0.00 reconn/s: 0.00
  19. [ 60s ] thds: 40 tps: 5458.66 qps: 5458.66 (r/w/o: 5458.66/0.00/0.00) lat (ms,95%): 17.63 err/s: 0.00 reconn/s: 0.00
  20. SQL statistics:
  21. queries performed:
  22. read: 316322
  23. write: 0
  24. other: 0
  25. total: 316322
  26. transactions: 316322 (5270.99 per sec.)
  27. queries: 316322 (5270.99 per sec.)
  28. ignored errors: 0 (0.00 per sec.)
  29. reconnects: 0 (0.00 per sec.)
  30. Throughput:
  31. events/s (eps): 5270.9892
  32. time elapsed: 60.0119s
  33. total number of events: 316322
  34. Latency (ms):
  35. min: 0.42
  36. avg: 7.59
  37. max: 858.18
  38. 95th percentile: 17.95
  39. sum: 2399738.58
  40. Threads fairness:
  41. events (avg/stddev): 7908.0500/53.41
  42. execution time (avg/stddev): 59.9935/0.00
  43. mysql version
  44. 5.7.22-log
  45. Variable_name Value
  46. Created_tmp_tables 316327

cpu使用率接近100%

  • mysql5.7.22 40个并发线程 压力测试60秒,访问I_S.tables 平均qps为5k,并创建了31w个临时表!

6、mysql8.0开启测试

  1. Shutting down MySQL.. SUCCESS!
  2. Starting MySQL.... SUCCESS!
  3. mysql version
  4. 8.0.15
  5. Variable_name Value
  6. Created_tmp_tables 1
  7. sysbench 1.1.0 (using bundled LuaJIT 2.1.0-beta3)
  8. Running the test with following options:
  9. Number of threads: 40
  10. Report intermediate results every 10 second(s)
  11. Initializing random number generator from current time
  12. Initializing worker threads...
  13. Threads started!
  14. [ 10s ] thds: 40 tps: 1283.76 qps: 1283.76 (r/w/o: 1283.76/0.00/0.00) lat (ms,95%): 41.10 err/s: 0.00 reconn/s: 0.00
  15. [ 20s ] thds: 40 tps: 1286.43 qps: 1286.43 (r/w/o: 1286.43/0.00/0.00) lat (ms,95%): 39.65 err/s: 0.00 reconn/s: 0.00
  16. [ 30s ] thds: 40 tps: 1333.00 qps: 1333.00 (r/w/o: 1333.00/0.00/0.00) lat (ms,95%): 37.56 err/s: 0.00 reconn/s: 0.00
  17. [ 40s ] thds: 40 tps: 1280.79 qps: 1280.79 (r/w/o: 1280.79/0.00/0.00) lat (ms,95%): 40.37 err/s: 0.00 reconn/s: 0.00
  18. [ 50s ] thds: 40 tps: 1313.57 qps: 1313.57 (r/w/o: 1313.57/0.00/0.00) lat (ms,95%): 38.94 err/s: 0.00 reconn/s: 0.00
  19. [ 60s ] thds: 40 tps: 1222.95 qps: 1222.95 (r/w/o: 1222.95/0.00/0.00) lat (ms,95%): 42.61 err/s: 0.00 reconn/s: 0.00
  20. SQL statistics:
  21. queries performed:
  22. read: 77248
  23. write: 0
  24. other: 0
  25. total: 77248
  26. transactions: 77248 (1286.95 per sec.)
  27. queries: 77248 (1286.95 per sec.)
  28. ignored errors: 0 (0.00 per sec.)
  29. reconnects: 0 (0.00 per sec.)
  30. Throughput:
  31. events/s (eps): 1286.9486
  32. time elapsed: 60.0242s
  33. total number of events: 77248
  34. Latency (ms):
  35. min: 1.88
  36. avg: 31.08
  37. max: 692.98
  38. 95th percentile: 40.37
  39. sum: 2400505.33
  40. Threads fairness:
  41. events (avg/stddev): 1931.2000/51.17
  42. execution time (avg/stddev): 60.0126/0.00
  43. mysql version
  44. 8.0.15
  45. Variable_name Value
  46. Created_tmp_tables 2

cpu使用率接近100%

  • mysql8.0.15 40个并发线程,压力测试60秒,访问I_S.tables 平均qps为1.2k,并创建了1个临时表!

结论

  • mysql8.0开始查询I_S中表不会再从文件系统(FRM, TRG,OPT文件)和myisam、innodb系统表读取元数据信息(8.0开始元数据信息统一存放在数据字典表中)
  • mysql8.0 访问I_S.tables不会创建临时表,这减少了内存暴涨的可能,但访问I_S.tables的qps大约是mysql5.7.22的1/5,访问速度没有mysql5.7.22的快
  • mysql8.0 访问I_S.tables 用户空间cpu消耗没有mysql5.7的高(没有创建临时表的缘故吧),但系统空间cpu消耗高于mysql5.7!

参考

MySQL 8.0: Improvements to Information_schema

MySQL 8.0 information_schema系统库的改进的更多相关文章

  1. MySQL 8.0 —— 数据字典

    1.简介 MySQL 8.0 将数据库元信息都存放于InnoDB存储引擎表中,在之前版本的MySQL中,数据字典不仅仅存放于特定的存储引擎表中,还存放于元数据文件.非事务性存储引擎表中.本文将会介绍M ...

  2. CentOS 7.x下安装部署MySQL 8.0实施手册

    MySQL 8 正式版 8.0.11 已发布,官方表示 MySQL 8 要比 MySQL 5.7 快 2 倍,还带来了大量的改进和更快的性能! 一.  Mysql8.0版本相比之前版本的一些特性 1) ...

  3. MySQL 8.0有什么新功能

    https://mysqlserverteam.com/whats-new-in-mysql-8-0-generally-available/ 我们自豪地宣布MySQL 8.0的一般可用性. 现在下载 ...

  4. mysql 8.0 初识

    1 下载并安装mysql 8.0官网下载比较慢,这里选择163的镜像http://mirrors.163.com/mysql/Downloads/MySQL-8.0/下载版本mysql-8.0.14- ...

  5. MySQL与MariaDB核心特性比较详细版v1.0(覆盖mysql 8.0/mariadb 10.3,包括优化、功能及维护)

    注:本文严禁任何形式的转载,原文使用word编写,为了大家阅读方便,提供pdf版下载. MySQL与MariaDB主要特性比较详细版v1.0(不含HA).pdf 链接:https://pan.baid ...

  6. MySQL 8.0 新特性梳理汇总

    一 历史版本发布回顾 从上图可以看出,基本遵循 5+3+3 模式 5---GA发布后,5年 就停止通用常规的更新了(功能不再更新了): 3---企业版的,+3年功能不再更新了: 3 ---完全停止更新 ...

  7. MySQL 8.0.0 版本发布,亮点都在这了!

    导读 MySQL是一个开放源码的小型关联式数据库管理系统,开发者为瑞典MySQL AB公司.目前MySQL被广泛地应用在Internet上的中小型网站中.由于其体积小.速度快.总体拥有成本低,尤其是开 ...

  8. What's New In MySQL 8.0

        由于8.0内有很多C++11特性.需要gcc4.8版本以上.Rhel6系列默认gcc是4.7.在安装gcc6.1之后仍然检查不过. 原因可能是6.1版本不一定高于4.7,暂不讨论.鉴于升级gc ...

  9. Centos 6.5下mysql 8.0.11的rpm包的安装方式

    1.系统版本及mysql下载地址 操作系统:Centos 6.5(Centos 7.4下载对应的mysql版本安装同理) mysql数据库版本:mysql8.0.11 mysql官方网站:http:/ ...

随机推荐

  1. 自绘LISTVIEW的滚动条(Delphi实现)

    因项目需要准备对LISTVIEW的滚动条进行自绘.于是在网上搜了一下,问题没解决,却搜出一篇令人不愉快的帖子 .确实,那时候实力是不够的,但现在应该是没问题了,为这个目的才不断磨练自己的. LISTV ...

  2. 三种方式配置Mac OS X的启动项

    在Mac OS X中,有三种方式来实现启动项的配置:1)Login Items:2)StartupItems:3)launchd daemon. 1.Login Items 打开System Pref ...

  3. Git基本用法(一)

    使用Git正常的工作流 创建/修改文件 使用git add <file1> <file2> <file3>...将文件添加至本地的缓冲区Index中 使用git c ...

  4. PE工具列表(看雪学院)

    PE编辑工具 Stud_PE v. 2.6.0.5 Stud_PE v.2.6.1.0 (2.61汉化版)   PE工具,用来学习PE格式十分方便. LordPE DLX增强版(2008.5.31) ...

  5. 一次C#和C++的实际应用性能比较(C++允许我们使用任何手段来提高效率,只要愿意做出足够的努力)

    05年时,在微软的Rico Mariani做了一次实际应用的C#和C++的性能比较.事情起源于微软著名的元老Raymond Chen(在下敬仰的超级牛人)用C++写了一个英汉词典程序,来描述讲解优化C ...

  6. delphi的Socket(有两种分别继承TObject和TComponent的方式)

    在Delphi中,对于Windows中的Socket进行了有效的封装.在Delphi中,按其继承关系,可以分层两类:一.TComponent--TAbstractSocket--TCustomSock ...

  7. 教你如何在 Visual Studio 2013 上使用 Github

    介绍 我承认越是能将事情变简单的工具我越会更多地使用它.尽管我已经知道了足够的命令来使用Github,但我宁愿它被集成到IDE中.在本教程中,我会告诉你使用Visual Studio 2013如何实现 ...

  8. CSocket实现端口扫描

    界面如下: 主要代码如下: //对于每一个线程,传过去的参数 typedef struct ThreadParamStruct { CString strIP; //要扫描的IP地址 UINT uPo ...

  9. .NET中扩展方法和Enumerable(System.Linq)

    LINQ是我最喜欢的功能之一,程序中到处是data.Where(x=x>5).Select(x)等等的代码,她使代码看起来更好,更容易编写,使用起来也超级方便,foreach使循环更加容易,而不 ...

  10. Python连载15-高阶函数&map映射

    一.高阶函数 1.定义:把函数作为参数使用的函数叫做高阶函数 (1)变量可以设置为赋值 a=100 b=a (2)函数名称就是一个变量 def FunA(): print("FunA()&q ...