Mysql调优常用命令以及执行计划

目录

一、性能检测工具

profile

performance_schema

processlist

二、mysql表设计

数据类型

时间类型

范式和反范式

其它一些方面

三、执行计划


一、性能检测工具

profile

        先执行语句:SHOW VARIABLES LIKE "%profiling%";查看当前数据库的配置是否启用profiling。如下图:

Mysql调优常用命令以及执行计划_第1张图片

         profiling显示为OFF,证明当前profiling监控命令无法使用,执行命令:set profiling = 1;启用profiling命令。

        下面介绍一下profiling的相关命令以及用途:

        1)show profiles;该命令可以查看最近执行的sql语句的执行时间,这个命令与上图中的profiling_history_size的值有关,默认值为15,也就意味着当使用该命令的是否可以查看最近15条sql语句的执行时间

Mysql调优常用命令以及执行计划_第2张图片

        2)show profile;如果不加任何参数可以查看最近执行的一条sql语句的详细执行时间,针对上图的话,就是query_id为7的sql语句的详细执行时间,如下图:

Mysql调优常用命令以及执行计划_第3张图片

         执行完该命令以后,可以清晰的查看到在执行select * from departments;这条sql语句的时候各阶段的执行时间,包含启动、权限校验、初始化、优化、准备、执行等。

        后面也可以追加指定参数,来查看指定query_id的详细执行时间,语句为:show profile for query query_id;也可以添加通过其它参数来查看其它性能信息,例如block io(io操作次数),context switches(上下文切换次数),cpu(显示用户cpu时间,系统cpu时间),IPC(发送和接收的消息数量),page faults(页错误数量),source(源码中函数名称与位置),all(所有性能信息)。使用方式为:show profile (for query query_id) cpu;

        需要注意的是,profiling性能监控在未来的版本中可能会被移除。

performance_schema

        可以通过语句:show variables like 'performance_schema';查看是否开启,如下图:

Mysql调优常用命令以及执行计划_第4张图片

         performance_schema是默认开启的,需要注意的是,performance_schema的开启和关闭只能通过修改配置文件的方式进行修改,不能通过语句进行设置。performance_schema的性能监控的信息是存储到performance_schema库中相关表中,这些表使用了performance_schema存储引擎,该存储引擎不会进行持久化。

        在进一步了解performance_schema之前,需要先了解以下两个概念:

        instruments:生产者,用于采集mysql操作过程中产生的事件信息,对应配置表中的配置项为监控采集配置项;

        consumers:消费者,对应的消费者表用于存储instruments采集的数据,对应配置表中的配置项为消费存储配置项。

        performance_schema库中的表大概分为以下几类:

        1)语句事件记录表,记录语句事件信息,通过show tables like '%statement%';进行查看有哪些表,其中events_statements_current记录当前事件,events_statements_history记录历史事件,events_statement_history_long记录长语句历史事件,summary记录相关摘要信息。

        2)等待记录事件表,show tables like '%wait%';该类包含的相关信息类似于语句时间记录表,例如events_waits_current,events_waits_history等;

        3)事务事件记录表,记录事件相关信息,show tables like '%transaction%';

        4)监控系统文件层调用的表,show tables like '%file%';

        5)监视内存使用的表,show tables like '%memory%';

        6)动态对performance_schema配置的配置表,show tables like '%setup%';

        需要注意的是,performance_schema性能监控是默认开启的,但是里面的监控项目并不是都是完全开启的,哪些处于开启哪些区域关闭,可以查看setup_instruments和setup_consumers这两张表,enabled的值为YES代表开启,NO为关闭。可以根据自己的需要开启监控项目。(timed代表计时器是否开启,只有instruments才会有)。

        以下面的一个监控开启为例:

        -- 打开等待事件的采集器配置

       update setup_instruments set enabled='YES', timed='YES' where name like 'wait%';

        -- 打开等待事件消费配置

        update setup_consumers set enabled='YES' where name like '%wait%';

        -- 查看当前服务server正在执行的任务

        select * from events_waits_current;

执行完上述语句以后,可以查看到下面的一些列信息

 对上面的一些字段进行一个解释:

thread_id:事件来自那个线程,事件的编号;

event_name:检测到的具体内容是什么

source:检测代码的源代码信息

timer_start:该事件的开始时间

timer_end:改时间的结束时间

timer_wait:该事件总的花费时间

举几个性能监控的例子:

1)各类sql的执行情况

        SELECT * FROM events_statements_summary_by_digest ORDER BY COUNT_STAR DESC;

2)各类sql的平均响应时间

        SELECT * events_statements_summary_by_digest ORDER BY COUNT_STAR DESC

3)各个表的物理IO使用情况

        SELECT * FROM table_io_waits_summary_by_table ORDER BY sum_timer_wait DESC

4)分析某条sql的执行情况

        SELECT * FROM events_statements_history WHERE sql_text LIKE '%count(*)%';

5)查询每个阶段的时间消耗

        SELECT * FROM events_stages_history_long WHERE NESTING_EVENT_ID = 1553;

6)查询每个阶段锁等待情况

        SELECT * FROM events_waits_history_longWHERE nesting_event_id = 1553;

        上面这些是对performance_schema的一个大致介绍,如果后续有机会,会详细介绍一下performance_schema的使用。

processlist

        可以查看当前数据库有多少链接,语句为show processlist;

        

 对上面的字段信息做一个介绍:

user:操作的用户

host:操作的主机地址

db:操作的数据库

command:标识当前状态。介绍几个状态:sleep线程等待客户端发送新的请求;query线程正在执行查询或者将结果返回给客户端;locked在server层,线程正在等待表锁;analyzing and statistics线程正在手机存储引擎的统计信息并生成查询的执行计划;copying to tmp table线程正在执行查询,并将查询结果存储到临时表中;sorting result线程正在对结果进行排序;sending data线程在多个状态之间传输数据或者生成结果集或者向客户端发送结果

time:语句的执行时间

state:命令的执行状态

info:正在执行的sql语句

二、mysql表设计

数据类型

        针对数据类型的优化,首先需要知道字段长度越小越好,在能确定字段长度的情况下,一定要选择最小的字段长度;还有数据类型的选择,越简单越好,能够使用数值类型就不要使用字符串类型;尽量避免null的使用,它会导致mysql本身无法对sql优化,也会导致索引失效。下面针对各种数据类型,进行详细的说明。

整数类型

        整数类型包含tinyint(8byte),smallint(16byte),mediumint(24byte),int(32byte),bigint(64byte),在设置为整数类型的时候,如果能确定数值的长度,选择最小的。还有一点需要注意,如果设置为int(10),如果存储的值大于10位长度,但是不能超过int类型允许的长度。

字符类型

        常见的字符类型有char和varchar,他们最大的区别是char为固定字符串,varchar为可变字符串,在不确定字符串长度的时候要选择varchar,并且要选择最小长度。char类型最大长度为255,并且会自动去除字符串后面的空格,如果确定字符串长度,例如md5值,可以选择char类型,它的检索效率和查询效率要高一些,用空间换时间。varchar类型需要注意一点,当字符串长度小于等于255的时候,使用额外一个字节存储字符串长度;当大于255时使用二外两个字节存储长度。在mysql以前的版本中,如果字段长度从255以下变到255以上的时候,会导致锁表。

        还有两个不经常使用的字符类型的字段:TEXT和BLOB。mysql在处理他们的时候,会当成一个独立的对象进行处理。TEXT使用字符类型存储,BLOB使用二进制类型进行存储,在进行表设计的时候,如果他们不为必须信息的时候,可以选择新建一个表进行存储这些信息,不要和主表放在一起,也可以将这些信息存储到文件中,在表中存储文件地址,当需要使用的时候,通过流去读取。

时间类型

        时间类型主要介绍以下三种:datetime,timestamp,date。

        datetime精确到毫秒级别,与时区无关,占用八个字节进行数据存储。它可以保存的数据范围很大,从1000-01-01 00:00:00~9999-12-31 23:59:59。

        timestamp精确到秒级别,与时区有关,要是用该类型的话,需要设置好时区,占用4个字节。它的数据范围为1970-01-01 00:00:00~2038-01-18 23:59:59。存储是采用整形进行的存储,他可以实现自动时间更新。目前在生产服务中,如果对时间没有特殊要求的话,基本都使用tamestamp。

        date精确到天级别,与时区无关,使用3个字节进行数据存储,它的存储范围为1000-01-01~9999-12-31。

特殊类型

        介绍一种特殊情况,ip地址的存储,使用整形去存储,使用的空间更少,而不要使用varchar去使用,可以通过一下两个函数:inet_aton('127.0.0.1')将ip转为整形,inet_ntoa(2130706433)将整形转为字符类型。使用这个函数的一个好处还可以防止ip地址有误。

范式和反范式

        首先了解一下三范式的概念:第一范式,表中业务字段,不可再分;第二范式,表中必须存在业务主键,非业务主键依赖于业务主键;第三范式,非业务主键不能相互依赖。

        范式的优点:可以更好的避免存储重复字段,更新速度快,并且范式化的表结构比较小,能够更好的存储到内存中;范式的缺点:在进行信息查询的时候,通常需要表关联。

        反范式的有点:避免进行表关联,在索引设置得当的情况下,查询效率高;反范式的缺点:表字段冗余过多,并且会造成数据的重复。

        在进行表设计的时候,不一定完全按照三范式的方式进行设计,为了提高查询效率可以适当添加冗余字段,范式和反范式混合使用,例如:订单表和用户表,如果有大量的业务查询是根据用户身份证号进行查询,可以在订单表中添加该冗余字段,这样每次查询就不需要进行多表关联查询。当然也要注意不能添加太多这种冗余字段,不然会对表结构造成很大影响。

其它一些方面

        主键的使用,主键分为以下两种:1)代理主键,与业务无关的主键,无意义的数字字符序列;自然主键,事务属性中的唯一表示,例如身份证。推荐使用代理主键,使用代理主键可以减少业务耦合。

        字符集的选择,在uft8编码格式下,针对不同范围的字符使用的存储字节数是不一样的,因此会造成一个字符需要两个字节或者三个字节进行存储,因此再mysql数据库中使用utf8mb4的字符集进行存储。当数据表的数据量很大的时候,可以针对字段类型设置字符集。

        存储引擎的选择,常用的数据引擎有innodb和myisam两种。myism使用非聚簇索引,它不支持事务,支持表锁和全文索引,适合select操作多的表;innodb使用聚簇索引,它支持事务,表级锁,行级锁,外键,全文索引(5.6以后),innodb加锁的时候是默认给索引加锁,它是建表时的默认存储引擎,适合insert,update,delete的相关操作。可以在建表的时候通过engine属性来实现。存储引擎代表的是数据文件的一个组织形式。

三、执行计划

        在我们进行mysql进行调优的时候,无法避免的去分析执行计划,通过在sql语句之前添加explain关键字,即可看到要执行的sql语句的执行计划信息,例如explain select * from employee;即可查看到这条语句的执行计划;

 下面我们针对执行计划中的这些字段进行一个了解:

id

        select的序列号,用来表示执行顺序。如果id值相同,那么执行顺序为从上到下执行;如果id值不同,id值越大优先级越高,就越先被执行。

select_type

        用来分辨查询的类型,执行的语句是普通查询还是关联查询等。介绍以下几种情况:

        sample:普通查询语句,例如select * from table_A;

        primary:查询中如果包含任何复杂的子查询,最外层被标记为primary,例如select column_A,column_B from (select column_A,column_B from table_A a) join table_B b on a.column_C = b. column_C;主查询就会被标记为primary;

        union:若第二个select出现在union之后,第二个select就会标记为union。例如select * from table_A where column_A > 20 union select * from table_A where column_B > 80;后面这条语句就会标识为union;

        subquery:在select或where列表中包含子查询,例如select * from table_A where column_A > (select AVG(column_B) from table_B);

table

        当前行正在访问的表名或者别名信息,也可能是临时表或者union的结果集。

type

        访问类型,表示我们以何种方式访问数据。访问类型的效率从最好到最坏依次是:

system->const->eq_ref->ref->fulltext->ref_or_null->index_merge->unique_subquery->index_subquery->range->index->all。下面针对这些数据访问类型进行一个基础说明。

        all:全表扫描,这种情况必须要进行优化。例如:select * from table_name;

        index:全索引扫描,有两种情况:一种是覆盖索引,一种是使用索引进行排序,例如:select column_A from table_A;其中colum_a为table_name的索引;

        range:利用索引查找时限制了范围,经常涉及到的运算符:>,is null,between,like等,例如select * from table_A where column_A > 100;其中column_A为table_A的索引;

        index_subquery:利用索引来关联子查询;

        unique_subquery:与index_subquery类似,只是使用的索引为唯一索引;

        index_merge:在查询过程中使用多个索引组合;

        ref_or_null:对于某个字段既需要指定条件,又需要为null的情况,例如select * from table_A where column_A = 100 and column_A is null;column_A为table_A的索引;

        ref:使用了非唯一索引进行数据查找;

        eq_ref:使用了唯一索引进行数据查找;

        const:这个表至多有一个匹配行;

        system:表中只有一条数据;

possible_keys

        该sql语句可能命中的表的索引,查询条件中涉及到的字段若存在索引,则该索引将会被列出,一个或者多个,但不一定被实际用到。

key

        实际使用的索引,如果为null,则代表没有使用索引,查询中若使用了覆盖索引,则该索引和select的字段重叠。(覆盖索引将会在下篇文章中详细介绍)

ken_len

        表示索引中使用的字节数,在不损失精度的情况下,长度越短越好。

ref

        显示索引的哪一列被使用,如果有可能的话,是一个常数,常数的时候显示为const,如果不是常数的时候显示的是表的索引列,例如employees.de.dept_no(库名.表名.列名)。

rows

        根据表的统计信息以及索引使用情况,大致估算出找出指定数据需要读取的数据行数。此参数在调优的时候很重要,扫描的条数越少越好。

extra

        记录额外信息,例句以下几种情况:

        impossible where:where语句的结果总是false;

        using where:使用where进行条件过滤;

        using index:查询中使用了覆盖索引;

        using temporary:建立临时表保存中间结果,查询完成以后把临时表删除;

        using filesort:无法利用索引排序,只能使用排序算法排序;

        

你可能感兴趣的:(mysql,java)