【MySQL索引与优化篇】数据库优化及性能分析工具使用

数据库优化及性能分析工具使用

文章目录

  • 数据库优化及性能分析工具使用
    • 1. 数据库服务器优化的步骤
    • 2. 查询系统性能参数
    • 3. 定位执行满的SQL:慢查询日志
    • 4. 查看SQL执行成本:show profile
    • 5. 分析查询工具:explain
      • 5.1 id
      • 5.2 type
    • 6. explain进一步使用
      • 6.1 explain支持4种输出格式
      • 6.2 show warnings
    • 7. 分析优化器执行计划:trace
    • 8. MySQL监控分析视图:sys_schema
      • 8.1 sys schema视图摘要
      • 8.2 sys schema使用场景
        • 索引情况
        • 表相关
        • 语句相关
        • IO相关
        • Innodb相关

1. 数据库服务器优化的步骤

  1. 观察服务器是否存在周期性波动,如淘宝双11等周期性活动,此时可考虑加缓存及更改缓存失效策略解决问题
  2. 开启慢查询日志记录,使用SHOW PROFILING和EXPLAIN分析,看是SQL等待时间长还是SQL执行时间长
    • SHOW PROFILING显示等待时间长,则调优服务器参数
    • SHOW PROFILING显示执行时间长,则结合EXPLAIN工具分析,考虑从以下3个方面进行优化
      1. 索引设计优化
      2. JOIN表过多,需要优化
      3. 数据库表设计优化
  3. 考虑SQL查询是否到达瓶颈,未到达则重新检查SQL,或再进行上述分析;已到达则考虑下面两步
    1. 读写分离(主从架构)
    2. 分库分表(垂直分库,垂直分表,水平分表)

数据库调优维度:

  • 索引失效,没有充分利用到索引——索引建立
  • 关联查询太多JOIN(设计缺陷或不得已的需求)——SQL优化
  • 服务器调优及各个参数设置(缓冲、线程数等)——调整my.cnf
  • 数据过多——分库分表

2. 查询系统性能参数

在MySQL中,可以使用 show status 语句查询数据库服务器的 性能参数执行频率

show [global|session] status like '参数';
  • Connections:连接MySQL服务器的次数
  • Uptime:服务器的上线时间,单位秒
  • Slow_queries:慢查询的次数
  • Innodb_rows_read/Innodb_rows_inserted/Innodb_rows_updated/Innodb_rows_deleted:查询对应操作查询或影响的行数
  • Com_select/Com_insert/Com_update/Com_delete:查询对应操作的次数
  • last_query_cost统计SQL的查询成本,返回上一条查询所需要读取的页的数量
    • 执行完 SQL 语句之后,通过查看当前会话中的 last_query_cost 变量值来得到当前查询的成本。它通常也是我们 评价一个查询的执行效率 的一个常用指标。这个查询成本对应的是 SQL 语句所需要读取的页的数量
    • 使用场景:它对于比较开销是非常有用的,特别是我们有好几种查询方式可选的时候

SQL 查询是一个动态的过程,从页加载的角度来看,我们可以得到以下两点结论

  1. 位置决定效率,页存在于内存中,会比在磁盘中读取效率高很多
  2. 批量决定效率,采用顺序读取的方式,批量对页进行读取,平均一页的读取效率就会提升很多

所以我们首先要考虑数据存放的位置,如果是经常使用的数据就要尽量放到 缓冲池 中,其次我们可以充分利用磁盘的吞吐能力,一次性批量读取数据,这样单个页的读取效率也就得到了提升。

3. 定位执行满的SQL:慢查询日志

慢查询日志会记录在MySQL中 响应时间超过阀值 的语句,具体指运行时间超过 long_query_time 值的SQL,则会被记录到慢查询日志中,默认值10(秒)

默认情况,MySQL数据库没有开启慢查询日志如果不是调优需要,一般不建议启动该参数(会带来一定的性能影响)

show [global|session] variables like '参数'

永久设置方式:修改my.cnf文件,[mysqld]下增加或修改参数long_query_time、slow_query_log、slow_query_log_file后,重启MySQL

[mysqld]
slow_query_log=ON # 慢查询日志开关
slow_query_log_file=/var/lib/mysql/slow_query_log.log # 慢查询日志位置
long_query_time=3 # 慢查询阈值,单位秒
log_output=FILE # 日志存储方式,log_output='TABLE'表示将日志存入数据库,这样日志信息就会被写入到mysql.slow_log表中

如果不指定存储路径,默认存储到MySQL的数据文件夹下;不指定文件名,默认为hostname-slow.log

慢日志分析工具mysqldumpslow,可以通过该工具按查询时间,平均查询时间等查看慢SQL日志情况

mysqldumpslow --help

删除慢查询日志:手动删除即可,之后执行如下命令重新生成查询日志文件

mysqladmin -uroot -p flush-logs slow

4. 查看SQL执行成本:show profile

Show Profile是MySQL提供的可以用来分析当前会话中SQL 都做了什么、执行的资源消耗情况的工具,可用于sql调优的测量。 默认情况下处于关闭状态 ,并保存最近15次的运行结果。

使用时建议用命令窗口登陆mysql再执行相应命令查看情况,使用界面工具直接执行会有很多干扰

show variables like 'profiling'; -- 查看开关
set profiling = 'ON'; -- 设置开关,ON|OFF
show profiles; -- 查看最近15次运行耗时
show profile; -- 查看上次sql各阶段执行时间,也可看information_schema.profiling表查看上面15次执行情况
show profile for query 82; -- 查看query_id为82的查询时间
show profile cpu,block io for query 1; -- 同时查看cpu和block io情况

在这里插入图片描述

executing:SQL的执行时间,如果该项时间过长,则考虑使用explain工具分析SQL进行SQL优化,否则看其他项考虑数据库参数配置优化

show profile常用参数

  1. all:显示所有的开销信息
  2. block io:显示块IO开销
  3. context switches:上下文切换开销
  4. cpu:显示CPU开销信息
  5. ipc:显示发送和接收开销信息
  6. memory:显示内存开销信息
  7. page faults:显示页面错误开销信息
  8. source:显示和Source_function,Source_file,Source_line相关的开销信息
  9. swaps:显示交换次数开销信息

日常开发需注意:

  1. converting HEAP to MyISAM:查询结果太大,内存不够,数据往磁盘上搬了
  2. Creating tmp table:创建临时表。先拷贝数据到临时表,用完后再删除临时表
  3. Copying to tmp table on disk:把内存中临时表复制到磁盘上,警惕!
  4. locked

如果在show profile诊断结果中出现了以上4条结果中的任何一条,则sql语句需要优化

注意: show profile 命令将被弃用,我们可以从 information_schema.profiling 数据表进行查看(会话级别),该表也只会保存最近15条SQL的执行情况

5. 分析查询工具:explain

MySQL提供了 explain 语句供查看SQL语句的具体执行计划,注意:部分统计信息是估算的,并非精确值

explain select 1;
列名描述
id每个select对应的唯一的id
select_typeselect关键字对应的那个查询的类型
table表名,每有一个表则对应一条数据,可能会有临时表
partitions匹配的分区信息
type针对单表的访问方法
possible_keys可能用到的索引
key实际上使用的索引
key_len单位字节,实际使用到的索引长度,主要针对于联合索引有参考意义
ref当使用索引列等值查询时,与索引列进行等值匹配的对象信息
rows预估的需要读取的记录条数,值越小越好
filtered某个表经过搜索条件过滤后剩余记录条数的百分比,连接查询中驱动表的执行计划记录的该值决定了被驱动表的执行次数(rows * filtered)
Extra描述SQL执行计划中的一些额外信息,更准确的描述MySQL到底如何执行给定的语句,主要规避:Using filesort和Using temporary

5.1 id

select对应的唯一id,当有多个表时会有多条记录如:

select * from s1 join s2; -- 根据table情况会有两行数据,但是select语句只有一条,故它们的id都是1

如果SQL语句中写有多个select,但id数无法对上,则表示优化器对sql进行了重写

  • id如果相同,可以认为是一组,从上往下顺序执行
  • 在所有组中,id值越大,优先级越高,越先执行
  • 关注点: 每个id,表示一趟独立的查询,一个sql的查询趟数越少越好

5.2 type

执行计划的一条记录就代表着MySQL对某个表的 执行查询时的访问方法,又称“访问类型”,其中的 type 列就表明了这个访问方法是啥,是较为重要的一个指标。比如,看到type 列的值是 ref,表明MySQL 即将使用 ref 访问方法来执行对 s1 表的查询

完整的访问方法: system,const,eq_ref,ref,fulltext,ref_or_null,index_merge,index_subquery,range,index,ALL

system:当表中只有一条记录,并且该表使用的存储引擎的统计数据是精确的,比如MyISAM和Memory

select count(*) from f1; -- f1使用MyISAM存储引擎,表中会记录记录数,故是system

const:主键或者唯一二级索引列与常数进行等值匹配时,对单表的访问方法就是const

select * from f1 where a = 1; -- a为主键或唯一索引

eq_ref:在连接查询时,如果被驱动表是通过主键或者唯一二级索引列等值匹配的方式进行访问的(如果该主键或者唯一二级索引是联合索引的话,所有的索引列都必须进行等值比较) ,则对该被驱动表的访问方法就是 eq_ref

select * from f1 join f2 on f1.id = f2.id; -- f1需要查全表,而对f2来说,驱动表f1的每条数据都能被被驱动表f2通过主键或唯一索引找到对应数据

ref:当通过普通的二级索引列与常量进行等值匹配时来查询某个表,那么对该表的访问方法就可能是 ref

select * from f1 where b = 'abc'; -- b为普通索引

ref_or_null:当对普通二级索引进行等值匹配查询,该索引列的值也可以是NULL值时,那么对该表的访问方法就可能是ref_or_null

select * from f1 where b = 'abc' or b is null; -- 在ref情况下增加还可能是null的情况

index_merge:单表访问方法时在某些场景下可以使用Union、Intersection、Sort-Union,这三种索引合并的方式来执行查询

select * from f1 where a = 'a' or b = 'b'; -- a和b均为索引,则会将a、b索引都用上

unique_subquery:是针对在一些包含 IN 子查询的查询语句中,如果查询优化器决定将 IN 子查询转化为 exists子查询,而且子查询可以使用到主键进行等值匹配的话,那么该子查询执行计划的 type列就是 unique_subquery

select * from f1 where b in ( select id from f2 where f1.a = f2.a) or c = 'abc'; -- id为f2的主键,类似于eq_ref

range:使用索引获取某些范围区间的记录,那么就可能使用到range访问方法

select * from f1 where b in ('a', 'b', 'c');
select * from f1 where b > 'a' and b < 'c';

index:当可以使用索引覆盖,但需要扫描全部的索引记录时,该表的访问方式就可能是index

select b from f1 where c = 'x'; -- f1上存在联合索引 a,b,c,查询时就不用回表了

小结,结果值从最好到最坏依次是:

system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL

SQL性能优化的目标:至少要达到 range 级别,要求是 ref 级别,最好是 const 级别 (阿里巴巴开发手册)

6. explain进一步使用

6.1 explain支持4种输出格式

传统、json、tree和可视化界面,其中Json比传统模式多了成本信息的打印,可视化界面需借助MySQL Workbench查看SQL的执行计划

explain format=json select * from f1;

6.2 show warnings

在使用explain后,紧接着使用show warnings语句可以查看与对应查询的查询计划有关的扩展信息,分别是 LevelCodeMessage

如果code值是1003,则表示有对SQL重写,通过show warnings的message可以查看到SQL优化后的执行语句

7. 分析优化器执行计划:trace

OPTIMIZER_TRACE 是MySQL 5.6引入的一项跟踪功能,它可以跟踪优化器做出的各种决策(比如访问表的方法各种开销计算、各种转换等),并将跟踪结果记录到 INFORMATION_SCHEMA.OPTIMIZER_TRACE 表中此功能默认关闭。开启trace,并设置格式为 JSON,同时设置trace最大能够使用的内存大小,避免解析过程中因为默认内存过小而不能够完整展示。这里仅做演示,不做详细剖析。

set optimizer_trace="enabled=on",end_markers_in_json=on;
set optimizer_trace_max_mem_size=1000000;
mysql> select * from INFORMATION_SCHEMA.OPTIMIZER_TRACE\G;
*************************** 1. row ***************************
/* 第1部分:SQL语句 */QUERY: select * from niuke.user_profile
/* 第2部分:QUERY字段对应语句的跟踪信息 */TRACE: {"steps": [{/* 预备工作 */"join_preparation": {"select#": 1,"steps": [{"expanded_query": "/* select#1 */ select `niuke`.`user_profile`.`id` AS `id`,`niuke`.`user_profile`.`device_id` AS `device_id`,`niuke`.`user_profile`.`gender` AS `gender`,`niuke`.`user_profile`.`age` AS `age`,`niuke`.`user_profile`.`university` AS `university`,`niuke`.`user_profile`.`gpa` AS `gpa`,`niuke`.`user_profile`.`active_days_within_30` AS `active_days_within_30`,`niuke`.`user_profile`.`question_cnt` AS `question_cnt`,`niuke`.`user_profile`.`answer_cnt` AS `answer_cnt` from `niuke`.`user_profile`"}] /* steps */} /* join_preparation */},{/* 进行优化 */"join_optimization": {"select#": 1,"steps": [{"table_dependencies": [{"table": "`niuke`.`user_profile`","row_may_be_null": false,"map_bit": 0,"depends_on_map_bits": [] /* depends_on_map_bits */}] /* table_dependencies */},{"rows_estimation": [{"table": "`niuke`.`user_profile`","table_scan": {"rows": 7,"cost": 0.25} /* table_scan */}] /* rows_estimation */},{"considered_execution_plans": [{"plan_prefix": [] /* plan_prefix */,"table": "`niuke`.`user_profile`","best_access_path": {"considered_access_paths": [{"rows_to_scan": 7,"access_type": "scan","resulting_rows": 7,"cost": 0.95,"chosen": true}] /* considered_access_paths */} /* best_access_path */,"condition_filtering_pct": 100,"rows_for_plan": 7,"cost_for_plan": 0.95,"chosen": true}] /* considered_execution_plans */},{"attaching_conditions_to_tables": {"original_condition": null,"attached_conditions_computation": [] /* attached_conditions_computation */,"attached_conditions_summary": [{"table": "`niuke`.`user_profile`","attached": null}] /* attached_conditions_summary */} /* attaching_conditions_to_tables */},{"finalizing_table_conditions": [] /* finalizing_table_conditions */},{"refine_plan": [{"table": "`niuke`.`user_profile`"}] /* refine_plan */}] /* steps */} /* join_optimization */},{"join_execution": {"select#": 1,"steps": [] /* steps */} /* join_execution */}] /* steps */
}
/* 第3部分:跟踪信息过长,被截断的部分 */
MISSING_BYTES_BEYOND_MAX_MEM_SIZE: 0
/* 第4部分:执行跟踪语句的用户是否有查看对象的权限。当不具备缺陷的时候,该列值为1,且trace字段为空,一般在调用带有存储过程的情况下会出现这种情况 */INSUFFICIENT_PRIVILEGES: 0
1 row in set (0.00 sec)

8. MySQL监控分析视图:sys_schema

关于MySQL的性能监控和问题诊断,我们一般都从 performance_schema 中去获取想要的数据,在MySQL5.7.7版本中新增 sys_schema,它将performance_schemainformation_schema中的数据以更容易理解的方式总结归纳为“视图”,其目的就是为了降低查询performance_schema的复杂度,让DBA能够快速的定位问题。都有哪些监控表和视图,掌握了这些,在我们开发和运维的过程中就起到了事半功倍的效果

8.1 sys schema视图摘要

  1. 主机相关:以host_summary开头,主要汇总了IO延迟的信息
  2. Innodb相关: 以innodb开头,汇总了innodb buffer信息和事务等待innodb锁的信息
  3. I/O相关: 以io开头,汇总了等待I/O、I/O使用量情况
  4. 内存使用情况:以memory开头,从主机、线程、事件等角度展示内存的使用情况
  5. 连接与会话信息:processlist和session相关视图,总结了会话相关信息
  6. 表相关: 以schema_table开头的视图,展示了表的统计信息
  7. 索引信息:统计了索引的使用情况,包含冗余索引和未使用的索引情况
  8. 语句相关:以statement开头,包含执行全表扫描、使用临时表、排序等的语句信息
  9. 用户相关:以user开头的视图,统计了用户使用的文件I/O、执行语句统计信息
  10. 等待事件相关信息:以wait开头,展示等待事件的延迟情况

8.2 sys schema使用场景

索引情况
# 1. 查询冗余索引
select * from sys.schema_redundant_indexes;
# 2. 查询未使用过的索引
select * from sys.schema_unused_indexes;
# 3. 查询索引的使用情况
select * from sys.schema_index_statistics where table_schema = 'dbname';
表相关
# 1. 查询表的访问量
select table_schema, table_name, sum(io_read_requests + io_write_requests) as io from sys.schema_table_statistics group by table_schema, table_name order by io desc;
# 2. 查询占用buffer pool较多的表
select object_schema,object_name,allocated,data from sys.innodb_buffer_stats_by_table order by allocated limit 10;
# 3. 查询表的全表扫描情况
select * from sys.statements_with_full_table_scans where db='dbname';
语句相关
# 1. 监控SQL执行的频率
select db,exec_count,query from sys.statement_analysis order by exec_count desc;
# 2. 监控使用了排序的SQL
select db,exec_count,first_seen,last_seen,query from sys.statements_with_sorting limit 1;
# 3. 监控使用了临时表或者磁盘临时表的SQL
select db,exec_count,tmp_tables,tmp_disk_tables,query from sys.statement_analysis where tmp_tables > 0 or tmp_disk_tables > 0 order by (tmp_tables + tmp_disk_tables) desc;
IO相关
# 1. 查看磁盘消耗IO文件
select file,avg_read,avg_write,avg_read + avg_write as avg_io from sys.io_global_by_file_by_bytes order by avg_read limit 10;
Innodb相关
# 1. 行锁阻塞情况
select * from sys.innodb_lock_waits;

风险提示:通过sys库去查询时,MySQL会 消耗大量资源 去收集相关信息,严重的可能会导致业务请求被阻塞,从而引起故障。建议生产上 不要频繁 的去查询sys或者performance_schema、information_schema来完成监控、巡检等工作

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/155220.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

作为20年老程序员,我如何使用GPT4来帮我写代码

如果你还在用google寻找解决代码bug的方案&#xff0c;那你真的out了&#xff0c;试试gpt4, save my life. 不是小编危言耸听&#xff0c;最近用gpt4来写代码极大地提高了代码生产力和运行效率&#xff0c;今天特地跟大家分享一下。 https://www.promptspower.comhttps://www.…

第7讲:VBA中利用FIND的代码实现多值查找实例

《VBA代码解决方案》(10028096)这套教程是我最早推出的教程&#xff0c;目前已经是第三版修订了。这套教程定位于入门后的提高&#xff0c;在学习这套教程过程中&#xff0c;侧重点是要理解及掌握我的“积木编程”思想。要灵活运用教程中的实例像搭积木一样把自己喜欢的代码摆好…

Unity DOTS系列之Struct Change核心机制分析

最近DOTS发布了正式的版本, 我们来分享一下DOTS里面Struct Change机制&#xff0c;方便大家上手学习掌握Unity DOTS开发。 基于ArchType与Chunk的Entity管理机制 我们回顾以下ECS的内存管理核心机制,基于ArchTypeChunk的Entity管理模式。每个Entity不直接存放数据&#xff0c…

[Python]unittest-单元测试

目录 unittest的大致构成: Test Fixture Test Case-测试用例 Test Suite-测试套件 Test Runner 批量执行脚本 makeSuite() TestLoader discover() 用例的执行顺序 忽略用例执行 skip skipIf skipUnless 断言 HTML测试报告 错误截图 unittest是python中的单元测…

亚马逊云科技为奇点云打造全面、安全、可扩展的数据分析解决方案

刘莹奇点云联合创始人、COO&#xff1a;伴随云计算的发展&#xff0c;数据技术也在快速迭代&#xff0c;成为客户迈入DT时代、实现高质量发展的关键引擎。我们很高兴能和云计算领域的领跑者亚马逊云科技一同&#xff0c;不断为客户提供安全可靠的产品与专业的服务。 超过1500家…

【操作系统】考研真题攻克与重点知识点剖析 - 第 1 篇:操作系统概述

前言 本文基础知识部分来自于b站&#xff1a;分享笔记的好人儿的思维导图与王道考研课程&#xff0c;感谢大佬的开源精神&#xff0c;习题来自老师划的重点以及考研真题。此前我尝试了完全使用Python或是结合大语言模型对考研真题进行数据清洗与可视化分析&#xff0c;本人技术…

面向制造企业的持续发展,2023数字化工单管理系统创新篇章-亿发

面向制造企业的持续发展&#xff0c;2023数字化工单管理系统开创新篇章-亿发 随着制造业的持续发展&#xff0c;运维工单管理日益成为关键环节&#xff0c;它设计客户管理、设备维护、服务商合作等多个业务领域&#xff0c;对运营效率和服务质量有着重要影响。然而&#xff0c…

【鸿蒙软件开发】ArkTS基础组件之TextTimer(文本显示计时)、TimePicker(时间选择)

文章目录 前言一、TextTimer1.1 子组件1.2 接口参数TextTimerController 1.3 属性1.4 事件1.5 示例代码 二、TimePicker2.1 子组件2.2 接口参数 2.3 属性2.4 事件TimePickerResult对象说明 2.5 示例代码 总结 前言 通过文本显示计时信息并控制其计时器状态的组件。 时间选择组…

什么是 CNN? 卷积神经网络? 怎么用 CNN 进行分类?(3)

参考视频&#xff1a;https://www.youtube.com/watch?vE5Z7FQp7AQQ&listPLuhqtP7jdD8CD6rOWy20INGM44kULvrHu 视频7&#xff1a;CNN 的全局架构 卷积层除了做卷积操作外&#xff0c;还要加上 bias &#xff0c;再经过非线性的函数&#xff0c;这么做的原因是 “scaled p…

前端环境的安装 Node npm yarn

一 node npm 1.下载NodeJS安装包 下载地址&#xff1a;Download | Node.js 2.开始安装 打开安装包后&#xff0c;一直Next即可。当然&#xff0c;建议还是修改一下安装位置&#xff0c;NodeJS默认安装位置为 C:\Program Files 3.验证是否安装成功 打开DOS命令界面&#…

深度学习之基于Pytorch卷积神经网络的图像分类系统

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介二、功能三、图像分类系统四. 总结 一项目简介 基于PyTorch卷积神经网络的图像分类系统是一种应用深度学习技术来实现图像分类任务的系统。本摘要将对该系统…

阿里云国际版和国内版的区别是什么,为什么很多人喜欢选择国际版?

阿里云国际版和国内版区别如下&#xff1a; 谈到区别&#xff0c;我们不妨先来对比下相同点与不同点&#xff0c;才能清晰明确的知道二者区别 下面先介绍不同点&#xff1a; 面向市场更广泛 阿里云国际版主要是面向国际&#xff08;全球&#xff09;客户的&#xff0c;而国内…