• mysql 慢查询


    1.开启慢查询

      查看开启状态:show variables like '%slow_query_log%';

      临时配置:set global slow_query_log=1;

      永久配置: [mysqld]下面增加

      slow_query_log=on

      slow_query_log_file=/usr/local/mysql/data/slow/mysql-slow.log 

      long_query_time=2

    2.开启全表扫描的语句记录

      查看开启状态:show VARIABLES like '%log_queries_not_using_indexes%' ;

      临时配置开启:set global log_queries_not_using_indexes=1;

      永久配置: [mysqld]下面增加   log_queries_not_using_indexes=on

    3.慢查询日志的输出

      查看配置状态:show variables like 'log_output';

    4.慢查询文件的分析工具

    time 查询时间
    user@Host 用户账号和ip 线程id
    query_time

    执行话费时长 时间是秒

    lock_time 执行获取锁的时间
    rows_sent 活得结果的行数
    rows_examined 扫描的行数
    SET timestamp 执行的具体时间  
    SQL语句  

    4.1mysqldumpslow

    -s                                                                  排序                                                        
    al 执行时获取锁时长平均值
    ar 返回行数的平均值
    at 查询时长的平均值
    c 查询次数
    l 获取锁时长
    r 获得返回行数
    t 执行总时长
    -t num 返回几行
    -g pattern 后面跟正则 筛选

    按照查询时间排序 取时间最长的前十个语句:mysqldumpslow -s t -t 10 -g select mysql-slow.log

    4.2pt-query-digest

    5.慢查询本质

      查询的数据太多,要确认是否请求了无用的行、列,如limit请求了无用的行,select *  一般而言请求了无用的列,请求的列越多,使用覆盖索引的几率越小 回表的概率越大,速度就会变慢。

      但是当在业务层缓存的时候可以用select *  缓存必须用在反复查询的场景里面

      复杂查询的where条件 是在引擎层查询后进行筛选的,所以where条件作用在引擎层会更能提高效率

    5.1.衡量查询开销的三个指标:响应时间、返回行数、扫描行数

      响应时间:服务时间和排队时间的总和

      服务时间:数据库处理这个查询真正花费的时间

      排队时间:服务器因等待某些资源没有真正的执行查询的时间,可能是等IO操作,也可能是等行锁释放的时间;

      所以通过成本计算可以算出这个响应时间是否合理

    5.2 返回行数和扫描行数

      理想的情况下返回行数和扫描行数应该相等。但是一些情况下 如limit会扫描超出需要行数很多的数据,该查询查找数据的效率不高

    5.3扫描行数和访问类型

      尽量适应高阶的访问类型 type,如果无法达到则尝试通过创建索引的方式;

    5.4where

      mysql使用where的三种方式,从效率和扫描行数来看从好到坏依次为

      1.在索引中使用where条件过滤不匹配的数据,这是在存储引擎层完成的;

      2.使用覆盖索引(extra 出现 using index) 来返回记录,直接从索引中过滤不需要的记录并返回结果,这是在mysql 服务层完成的但无需要回表查询;

      3.从数据表中返回数据,然后在过滤不满足条件的记录(在extra 中出现using where) 这是在server层完成过滤的;

    5.4优化策略:1) 采用覆盖索引

           2)更改表结构,采用反范式设计表结果, 减少联合查询

           3)重构sql 复杂查询 分成简单查询,在业务层更好扩展,sql语句是脚本语言 维护起来比较困难;切分查询,每次查询的数据量要控制在 5000~10000之间  

           4)查看整个sql执行的过程 是否存在吞吐量过大,tcp半双工引起的请求拥挤问题

    5.5sql查询执行的全流程

      如果把查询sql看成一个任务,那么它有一系列的子任务组成,每个子任务都会消耗掉一本部分的时间,实际上要优化其子任务要么消除掉其中一些子任务,要么减少子任务的执行次数,要么让子任务执行更快。

      执行流程:

      1.客户端发送一条查询给服务器;

      2.服务器先查询缓存中是否有结果,如果有直接返回,没有缓存则进入下一阶段(sql8.0后该模块没有了)

      3.sever层进行解析 预处理 再由优化器生成执行计划;

      4.mysql根据优化器生成的执行计划调用存储引擎层的api执行查询

      5.结果返回给客户端

    5.6 mysql 客户端和服务器通讯

      他们之间的通讯协议是半双工的,这就意味着在任何一个时刻,要么服务器向客户端发送数据 要么客户端向服务器发数据,这两个过程不能同时存在。

      当客户端用一个单独的数据包将查询传送给服务器的时候 sql查询语句很长,需要设置max_allowed_packet。

      当服务器向客户端发送数据的时候,客户端必须完整的接受整个结果,保证服务器尽快传送完数据,释放资源。jdbc的库函数会逐条接受数据库传送过来的数据进行缓存,等完全传送完,业务层就可以调用了,有时候传送的数据太多可能引起OOM;

      所以MySQL的JDBC里提供了setFetchSize()之类的功能,来解决这个问题:

      1、当statement设置以下属性时,采用的是流数据接收方式,每次只从服务器接收部份数据,直到所有数据处理完毕,不会发生JVMOOM。  

    setResultSetType(ResultSet.TYPE_FORWARD_ONLY);

    setFetchSize(Integer.MIN_VALUE);  

    2、调用statement的enableStreamingResults方法,实际上enableStreamingResults方法内部封装的就是第1种方式。

    3、设置连接属性useCursorFetch=true(5.0版驱动开始支持),statement以TYPE_FORWARD_ONLY打开,再设置fetchsize参数,表示采用服务器端游标,每次从服务器取fetch_size条数据。比如:con=DriverManager.getConnection(url);

    ps=(PreparedStatement)

    con.prepareStatement(sql,ResultSet.TYPE_FORWARD_ONLY,ResultSet.CONCUR_READ_ONLY);

    ps.setFetchSize(Integer.MIN_VALUE);

    ps.setFetchDirection(ResultSet.FETCH_REVERSE);

    rs=ps.executeQuery();

    while(rs.next()){……实际的业务处理}  

     5.7优化器

      静态优化器:编译时优化

      动态优化器:运行时优化

    5.8线程状态

      show processlist 可以查看线程状态

      

     线程状态的官方文档:https://dev.mysql.com/doc/refman/8.0/en/general-thread-states.html

    5.9 show profile

      查看是否支持profile :select @@have_profiling;

      

      查看状态:show @@profiling 

      更改状态:set profiling=1;

       查询语句后面紧跟show profiles 查看当前查询语句的queryid 

      

     

      查看这天语句的执行过程用时:

      show profile for query 30;
      show profile all for query 30;

     

     

  • 相关阅读:
    IT教育课程考评系统开发-07
    2020091201-1
    ip
    输入框枚举
    语言枚举
    《岁月神偷》弹唱和弦吉他谱_六线谱
    string 转化成 string数组
    获取类的字段值
    获取类的字段
    最全的省份递归
  • 原文地址:https://www.cnblogs.com/xiatc/p/16305943.html
Copyright © 2020-2023  润新知