SQL优化

本文请结合《索引,索引优化,mysql索引失效场景》食用。(https://www.cnblogs.com/lpeng94/p/12546455.html

监控项:

  • 网络相关
    • Bytes_received
    • Bytes_sent
    • TPS:Transaction Per Second,每秒事务处理量
    • Com_commit
    • Com_rollback
  • 连接相关
    • created_tmp_disk_use
    • connections
    • connection_errors_max_connections
    • threads_created
  • 负载相关

    • innodb_rows_deleted
    • innodb_rows_inserted
    • innodb_rows_read #异常高时,说明系统处理了过多的行。此时要去找SQL。而SQL在的地方:慢查询里或show processlist里。
    • innodb_rows_updated
    • sort_rows
  • QPS: Query Per Second,每秒查询率

    • Queries
    • Com_delete
    • Com_insert
    • Com_insert_select
    • Com_select
    • Com_update
  • 内存相关
    • innodb_buffer_pool_pages_data
    • innodb_buffer_pool_pages_free
    • innodb_buffer_pool_pages_dirty
  • IO相关
    • innodb_buffer_pool_pages_flushed #flushed 忽然高起来,说明是写的问题。比如logfile过小之类的
    • innodb_buffer_pool_wait_free
    • innodb_data_reads
    • innodb_log_waits
  • 锁相关
    • innodb_row_lock_waits
  • 排序相关
    • sort_merge_passes
  • SQL相关
    • select_full_join
    • select_scan
  • 慢查询相关
    • slow_queries

优化整理思路

1、OS操作系统层面监控主要的资源消耗

  • io:io负载是否过量(iostat 1 -x)
  • cpu:多个cpu是否繁忙
    • (mpstat -A 1 #能够看到每颗cpu)
    • (vmstat 1 #能看整体的)
  • 内存: 内存是否消耗殆尽,产生了swap
  • 网络:带宽

2、mysql数据库层面监控
注:OS底层只能说明出来io很高,mysql层面可以具体的告诉我们是哪些具体的原因导致的。
(1)负载突然增加

表现:tps、qps忽然增加。

(2)tps、qps并没增加,但是处理行数的系统负载突然增加
表现:innodb_rows_read 高

说明糟糕的sql出现了 #此值等于sql实际处理的行数。处理的行数就是负载。

什么是糟糕的sql?:

  • ①正在慢的sql
show full processlist G ;

explain 看sql的执行计划 ;
模拟执行这个sql:explain SQL语句 for update; 看结构。然后执行sql,看执行的时间(1s就不正常了)!

  • ②已经慢的sql -> slow-log里
  • ③全表扫描的sql

(3)写负载忽然增加

  • ①是否有异常的dml

表现:负载相关参数的row_deleted、rows_inserted、rows_updated 会很高。 可能的原因:批量的增删改、异常的checkpoint。

  • ②logfile过小
  • ③电池是否异常

对于慢sql,有两个执行步骤。

  • ①执行计划的显示和排错
  • ②模拟执行sql

导流的方式来进行压力测试(网络层面tcp copy)

这里写图片描述


对于select语句来说,可以直接执行;
对于dml:

  • ①insert 和 insert select
eg:insert into t1 select * from t2 where id<1000; 
(慢在select)
[select * from t1 where id<1000;]
  • ②delete …where
eg:delete from t1 where id < 1000; (实质还是要先找到,才能删)
  • ③update …where
eg:update t1 set name='abc' where id <1000;
[select * from t1 where id<1000;]

select语句的执行顺序和负载点分析

explain select ... from stock where s_i_id = 65534 and s_w_id = 1 for update;

如何判断一个SQL很糟糕

  • ①explain执行计划判断

id:查询序号即为sql语句执行的顺序
select_type:select类型

[ simple 它表示简单的select,没有union和子查询;primary 最外面的select,在有子查询的语句中,最外面的select查询就是primary;union union语句的第二个或者说是后面那一个;dependent union UNION中的第二个或后面的SELECT语句,取决于外面的查询;union result]

  • table:访问哪个表
  • type:连接类型(all、ref……)(重要且难)
  • possible_keys:访问这张表有哪些列可以选
  • key:最后走了哪个索引列
  • key_len:索引列的长度
  • rows:这条sql实际要访问的行数;
  • extra:回表,用了什么。

这里写图片描述
(会访问97934行,然后才返回4行(我们预测的),所以是个糟糕的sql)
这里写图片描述
(访问10行,返回4行,效果很好)

  • ②执行判断
    • 1.看执行时间
    • 2.看实际访问行数
show table status like ''%t1%;  
#能看一个表有多少行
show index from stock;      
#看表的 索引、列、card(基数,即列的值数,越高越好)

这里写图片描述

Cardinality:这个列有238778个值。假设这个表一共有95万行,而s_i_id 这个列有23万个值。即:一个值有 4 行 –>
select * from 这个列 where … 平均返回4行
show create table stock G
desc stock;


优化查询:
添加索引
在生产中添加索引的风险:

  • ①产生锁(如果表大的话,一个alter语句可能要好几天才完成)
  • ②执行时间可能非常长,资源消耗非常大

慢查询
看慢sql的时候可以去看slow sql 的日志。慢查询的sql都在里面存着。
慢查询日志会很大,怎么看?
这里写图片描述

mysqldumpslow 选项 slowmysql.log

  • -r:反序排序
  • -t 10:显示前10个
  • -s:按什么来排序
  • -t:按查询时间(即显示出来的是最慢的几条,往下查询时间依次递减)
  • -r:按处理的行数
  • -l:按锁的时间
  • -c:按count
  • -al:按平均锁的时间
  • -ar:按平均处理的行数
  • -at:按平均查询时间(默认是at)

经典的工具

  • explain命令
  • show create table 命令
  • show indexes 命令
  • show table status命令
  • show status命令
  • show variables 命令
原文地址:https://www.cnblogs.com/lpeng94/p/12546459.html