mysql调优 一

mysql调优 一

调优前的准备,本篇包含三部分 sql的性能监控,数据类型的优化及执行计划的使用。



一、性能查看

1、show profile

该工具默认是禁用的,可以设置打开。该工具可以比较粗略的查看sql的执行时长及占用资源,比较便捷。
在命令行中设置并使用:

set profiling=1;  //打开查询,设置完成之后,在服务器上执行的所有语句,都会测量其耗费的时间和其他一些查询执行状态变更相关的数据。
select * from 表 .....;  //执行具体的相关sql语句
show profiles;  //查看具体sql的执行时间
show profile for query 1;  //最后面的1对应上面show profiles的id号,查看详细每个步骤的耗时
show profile all for query 1; //ALL这可以配置需要查看的信息,ALL为查看占用资源的全部信息。

在查询窗口中设置并使用

SHOW VARIABLES LIKE 'profiling';  -- 查看开关的打开状态
SET profiling=ON; -- 打开开关
select * from 表 .....;  -- 执行具体的相关sql语句
SHOW PROFILES;  -- 查看具体sql的执行时间
SHOW PROFILE ALL FOR QUERY 1;  -- 最后面的1对应上面show profiles的id号,ALL这可以配置需要查看的信息,ALL为查看占用资源的全部信息。

附ALL这可以查看的相关信息

block io:显示块io操作的次数
context switches:显示上下文切换次数,被动和主动
cpu:显示用户cpu时间、系统cpu时间
IPC:显示发送和接受的消息数量
page faults:显示页错误数量
source:显示源码中的函数名称与位置
swaps:显示swap的次数

2、performance schema

相当于增强版的监控mysql在运行过程中的资源消耗资源等待情况,比较细致,可以基于监控的数据performance_schema库来做一个监控数据库信息的产品。在5.7中改功能是默认开启的。
特点及配置使用详见:performance schema使用详解
比较实用性的使用:

-- 哪类的SQL执行最多
SELECT DIGEST_TEXT,COUNT_STAR,FIRST_SEEN,LAST_SEEN FROM events_statements_summary_by_digest ORDER BY COUNT_STAR DESC
-- 哪类SQL的平均响应时间最多
SELECT DIGEST_TEXT,AVG_TIMER_WAIT FROM events_statements_summary_by_digest ORDER BY COUNT_STAR DESC
-- 哪类SQL排序记录数最多
SELECT DIGEST_TEXT,SUM_SORT_ROWS FROM events_statements_summary_by_digest ORDER BY COUNT_STAR DESC
-- 哪类SQL扫描记录数最多
SELECT DIGEST_TEXT,SUM_ROWS_EXAMINED FROM events_statements_summary_by_digest ORDER BY COUNT_STAR DESC
-- 哪类SQL使用临时表最多
SELECT DIGEST_TEXT,SUM_CREATED_TMP_TABLES,SUM_CREATED_TMP_DISK_TABLES FROM events_statements_summary_by_digest ORDER BY COUNT_STAR DESC
-- 哪类SQL返回结果集最多
SELECT DIGEST_TEXT,SUM_ROWS_SENT FROM events_statements_summary_by_digest ORDER BY COUNT_STAR DESC
-- 哪个表物理IO最多
SELECT file_name,event_name,SUM_NUMBER_OF_BYTES_READ,SUM_NUMBER_OF_BYTES_WRITE FROM file_summary_by_instance ORDER BY SUM_NUMBER_OF_BYTES_READ + SUM_NUMBER_OF_BYTES_WRITE DESC
-- 哪个表逻辑IO最多
SELECT object_name,COUNT_READ,COUNT_WRITE,COUNT_FETCH,SUM_TIMER_WAIT FROM table_io_waits_summary_by_table ORDER BY sum_timer_wait DESC
-- 哪个索引访问最多
SELECT OBJECT_NAME,INDEX_NAME,COUNT_FETCH,COUNT_INSERT,COUNT_UPDATE,COUNT_DELETE FROM table_io_waits_summary_by_index_usage ORDER BY SUM_TIMER_WAIT DESC
-- 哪个索引从来没有用过
SELECT OBJECT_SCHEMA,OBJECT_NAME,INDEX_NAME FROM table_io_waits_summary_by_index_usage WHERE INDEX_NAME IS NOT NULL AND COUNT_STAR = 0 AND OBJECT_SCHEMA <> 'mysql' ORDER BY OBJECT_SCHEMA,OBJECT_NAME;
-- 哪个等待事件消耗时间最多
SELECT EVENT_NAME,COUNT_STAR,SUM_TIMER_WAIT,AVG_TIMER_WAIT FROM events_waits_summary_global_by_event_name WHERE event_name != 'idle' ORDER BY SUM_TIMER_WAIT DESC
-- 剖析某条SQL的执行情况,包括statement信息,stege信息,wait信息
SELECT EVENT_ID,sql_text FROM events_statements_history WHERE sql_text LIKE '%count(*)%';
-- 查看每个阶段的时间消耗
SELECT event_id,EVENT_NAME,SOURCE,TIMER_END - TIMER_START FROM events_stages_history_long WHERE NESTING_EVENT_ID = 具体id;
-- 查看每个阶段的锁等待情况
SELECT event_id,event_name,source,timer_wait,object_name,index_name,operation,nesting_event_id FROM events_waits_history_longWHERE nesting_event_id = 具体id;

3、show processlist

用来查看连接的线程个数,不过现在都是用的线程池,所以该命令并不常用。

id表示session id
user表示操作的用户
host表示操作的主机
db表示操作的数据库
command表示当前状态(sleep:线程正在等待客户端发送新的请求,query:线程正在执行查询或正在将结果发送给客户端,
locked:在mysql的服务层,该线程正在等待表锁,analyzing and statistics:线程正在收集存储引擎的统计信息,
并生成查询的执行计划,Copying to tmp table:线程正在执行查询,并且将其结果集都复制到一个临时表中,
sorting result:线程正在对结果集进行排序,sending data:线程可能在多个状态之间传送数据,或者在生成结果集或者向客户端返回数据)
info表示详细的sql语句
time表示相应命令执行时间
state表示命令执行状态

二、基础性优化

1.数据类型优化:

 1> 尽量使用可以正确存储数据的最小数据类型(占用更少的磁盘、内存和CPU缓存,并且处理时需要的CPU周期更少)。
 2> 尽量使用简单数据类型(1、整型比字符操作代价更低,因为字符集和校对规则是字符比较比整型比较更复杂。2、使用mysql自建类型而不是字符串来存储日期和时间。3、用整型存储IP地址 如何使用在下面详述 )
 3> 尽量避免字段null(可为null的列使得索引、索引统计和值比较都更加复杂)
 4> 各数据类型细则:
 整数类型:
看需求尽量使用最小数据类型。TINYINT,SMALLINT,MEDIUMINT,INT,BIGINT分别使用8,16,24,32,64位存储空间

 字符和字符串类型:
varchar根据实际内容长度保存数据,使用最小的符合需求长度。
应用场景:a、存储长度波动较大的数据;b、字符串很少更新的场景,每次更新后都会重算并使用额外存储空间保存长度;c、多字节字符;
varchar(10)与varchar(255)保存同样的内容,硬盘存储空间相同,但内存空间占用不同,是指定的大小 。指定的长度小于等于255使用额外一个字节保存长度,大于255使用额外两个字节保存长度。在mysql5.6之前变更长度会导致锁表。
char固定长度的字符串,最大长度为255,会自动删除末尾的空格,检索效率、写效率 会比varchar高,以空间换时间。
应用场景:a、存储长度波动不大的数据;b、存储短字符串、经常更新的字符串;

 BLOB 和 TEXT 类型:
两者都是把值当做一个独立的对象处理,为了存储很大数据而存在的字符串类型,分别采用二进制和字符方式存储。

 日期时间类型:
注:不要使用字符串存储日期类型,占用空间大,损失日期类型函数的便捷性
datetime:占用8字节;与时区无关,数据库底层时区配置,对datetime无效;可保存到毫秒;可保存时间范围大;
timestamp:占用4字节;时间范围是1970-01-01到2038-01-19;精确到秒;采用整形存储;依赖数据库设置的时区;自动更新timestamp列的值。
date:占用的字节数比使用字符串、datetime、int存储要少,使用date类型只需要3个字节;使用date类型还可以利用日期时间函数进行日期之间的计算;date类型用于保存1000-01-01到9999-12-31之间的日期。

 枚举类
应用场景:配置类翻译类字段可以使用枚举类代替常用的字符串类型;mysql在内部会将每个值在列表中的位置保存为整数,并且在表的.frm文件中保存“数字-字符串”映射关系的查找表。 create table enum_type(type enum('0','1','2') not null); insert into enum_type(type) values('无效'),('生效中'),('预生效');
select type +0 from enum_type;

特殊类型:
像是上面说到的存地址使用INT来存储ip地址(本质是32位无符号整数),用INET_ATON()和INET_NTOA函数在这两种表示方法之间转换。
例:INET_ATON('192.168.22.2')与INET_NTOA(3232241154)

2、范式

 范式和反范式结合使用
 范式:
优点:a、范式化的更新通常比反范式要快;b、当数据较好的范式化后,很少或者没有重复的数据;c、范式化的数据比较小,可以放在内存中,操作比较快;     
缺点:一般需要进行很多关联;
 反范式:
优点:a、所有的数据都在同一张表中,可以避免关联;b、可以设计有效的索引;    
缺点:表格内的冗余较多,删除数据时候会造成表有些有用的信息丢失;

3、主键

 主键可以分为两类代理主键(与业务无关的,无意义的数字序列)和自然主键(事物属性中的自然唯一标识)。
推荐使用代理主键:它们不与业务耦合,因此更容易维护;一个大多数表,最好是全部表,通用的键策略能够减少需要编写的源码数量,减少系统的总体拥有成本。

4、字符集

  同样的内容使用不同字符集表示所占用的空间大小会有较大的差异;使用合适的字符集,可以尽可能减少数据量,进而减少IO操作次数。
a、纯拉丁字符可以表示全部内容就选择latin1 ,会节省大量的存储空间。
b、不需要存放多种语言,就尽量不要使用UTF8或者其他UNICODE字符类型,节省存储空间。
c、MySQL的数据类型可以精确到字段,可以通过对不同表不同字段使用不同的数据类型来较大程度减小数据存储量,进而降低 IO 操作次数并提高缓存命中率。

5、存储引擎

   常用三种 InnoDB 、MyISAM 、Memory(是基于内存的)。
一般都是用InnoDB,具体区别后面详述。 ![存储引擎对比](https://img-blog.csdnimg.cn/20210105105939241.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80OTQ0MjY1OA==,size_16,color_FFFFFF,t_70) ## 6、数据冗余/拆分   a、对于被频繁引用且只能通过 Join 多张大表的方式才能得到的独立小字段,可以做适当的数据冗余,同一字段在多表中存在,通过空间换取时间。
b、对于TEXT 或者是很大的 VARCHAR类型的大字段,如果查询很少用到该字段那么需要把该字段拆到独立表中,减少常用数据占用的存储空间。可以达到增加数据块中存储数据条数,减少物理io次数,提高内存中的缓存命中率。

三、执行计划

通过EXPLAIN + sql语句来查看具体sql语句的执行计划,看到具体是如何处理sql语句的。

1.字段详解

ID:
语句中执行select子句或者操作表的顺序
a、如果id相同,那么执行顺序从上到下;b、如果id不同,id值越大优先级越高,越先被执行

SELECT_TYPE:
用来分辨查询的类型,每个值代表含义如下:
a、sample:简单的查询,不包含子查询和union;b、primary:查询中若包含任何复杂的子查询,最外层查询则被标记为Primary;c、union:若第二个select出现在union之后,则被标记为union;d、dependent union:depentent表示union或union all联合而成的结果会受外部表影响;e、union result:从union表获取结果的select;f、subquery:在select或者where列表中包含子查询;g、dependent subquery:subquery的子查询要受到外部表查询的影响;h、DERIVED: from子句中出现的子查询;

TABLE:
对应行正在访问哪一个表,表名或者别名,可能是临时表或者union合并结果集。
a、如果是具体的表名,则表明从实际的物理表中获取数据;b、表名是derivedN的形式,表示使用了id为N的查询产生的衍生表;c、表名是union n1,n2...的形式,n1,n2...表示参与union的id

TYPE:
访问类型,访问类型的效率由好到坏:system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL
一般情况至少要到range级别,最好达到ref。
all:全表扫描,一般情况下出现这样的sql语句而且数据量比较大的话那么就需要进行优化;
index:全索引扫描,查询时覆盖索引需要的数据在索引中可以索取或者是使用了索引进行排序;
range:表示利用索引查询的时候限制了范围,避免了index的全索引扫描。=, <>, >, >=, <, <=, IS NULL, BETWEEN, LIKE, or IN()等等
index_subquery:利用索引来关联子查询,不再扫描全表
unique_subquery:类似index_subquery,使用的是唯一索引
index_merge:在查询过程中需要多个索引组合使用
ref:使用了非唯一性索引进行数据的查找
eq_ref :使用唯一性索引进行数据查找
const:该表至多有一个匹配行
system:表只有一行记录


POSSIBLE_KEYS:
可能应用在这张表中的索引,不一定被用到。

KEY:
实际使用的索引,如果为null,则没有使用索引。

KEY_LEN:
表示索引中使用的字节数,通过该值计算查询中使用的索引长度。

REF:
显示索引的哪一列被使用

ROWS:
大致估算出找出所需记录需要读取的行数,完成需求情况下该值越小越好。

猜你喜欢

转载自blog.csdn.net/weixin_49442658/article/details/112180149