MySQ5.7数据库-基准测试SQL语句分析
文章目录
- MySQL基准测试
- 什么是基准测试
- 基准测试特点
- 压力测试特点
- 基准测试的目的
- 如何进行基准测试
- 对整个系统进行基准测试
- MySQL基准测试的常见指标
- MySQL基准测试之mysqlslap
- 常见参数说明
- SQL语句分析
- 影响服务器性能的几个方面
- SQL性能下降原因
- MySQL常见瓶颈
- explain分析SQL语句
- explain是什么?
- explain能干什么?
- explain使用
- explain字段解释
- id表的读取顺序
- select_type
- table
- partitions
- type
- possible_keys
- key
- key_len
- 索引长度计算
- ref
- rows
- Extra
- Show Profile进行SQL分析
- Show Profile分析步骤
- type
- 参数注意
- 全局查询日志
- trace分析SQL优化器
- trace分析SQL优化器介绍
- 使用trace进行分析
- 总结
MySQL基准测试
什么是基准测试
- 基准测试是一种测量和评估软件性能指标的活动用于建立某个时刻的性能基准,以便当系统发生软硬件变化时重新进行基准测试以评估变化对性能的影响。
- 基准测试时针对系统设置的一种压力测试
基准测试特点
- 直接、简单、易于比较,用于评估服务器的处理能力
- 可能不关心业务逻辑,所使用的查询和业务的真实性可以和业务环境没关系
压力测试特点
- 对真实的业务数据进行测试,获得真实系统所能承受的压力
- 需要针对不同主题,所使用的数据和查询也是真实用到的
- 基准测试是简化了的压力测试
基准测试的目的
- 建立MySQL服务器的性能基准线,确定当前MySQL服务器运行情况,确定优化之后的效果
- 模拟比当前系统更高的负载,已找出系统的扩展瓶颈,可以增加数据库并发,观察QPS(每秒处理的事务数)变化,确定并发量与性能最优的关系
- 测试不同的硬件、软件和操作系统配置
- 证明新的硬件设备是否配置正确
如何进行基准测试
对整个系统进行基准测试
优点
- 能够测试整个系统的性能,包括web服务器缓存、数据库等
- MySQL并不总是出现性能问题的瓶颈,如果只关注MySQL可能忽略其他问题,能反映出系统中各个组件接口间的性能问题体现真实性能状况
缺点
- 基准测试最重要的就是简单,可能对不同的方案进行测试,找到最优的方案,基准测试进行的时间一定要短,否则就要花费大量的时间进行基准测试
- 测试设计复杂,消耗时间长
MySQL基准测试的常见指标
- 单位时间内处理的事务数
- 单位时间内处理的查询数
- 响应时间
MySQL基准测试之mysqlslap
- 可以模拟服务器负载,并输出相关统计信息
常见参数说明
注意: 真实的表不要进行测试,否则测试完,表就不会存在了
- –auto-generate-sql :由系统自动生成SQL脚本进行测试
- –auto-generate-sql-add-autoincrement : 在生成的表中增加自增ID
- –auto-generate-sql-load-type: 指定测试中使用的查询类型 读写或者混合,默认是混合
- –auto-generate-sql-write-number :指定初始化数据时生成的数据量
- –concurrency : 指定并发线程的数量1,10, 50, 200, 当测试超过两百时,需要进行测试
- –engine: 指定要测试表的存储引擎,可以用逗号分割多个存储引擎
- –no-drop : 指定不清理测试数据
- –iterations : 指定测试运行的次数,指定了这个不能指定的no-drop
- –number-of-queries : 指定每一个线程执行的查询数量
- –debug-info : 指定输出额外的内存及CPU统计信息
- –number-int-cols :指定测试表中包含的int类型列的数量
- –number-char-cols : 指定测试表中包含的varchar类型的数量
- –create-schema: 指定了用于执行测试的数据库的名字
- –query: 用于指定自定义SQL的脚本
- –only-print : 并不运行测试脚本,而是把生成的脚本打印出来
mysqlslap --concurrency=1,50,100,1000 --iterations=3 --number-int-cols=5 --number-char-cols=5 --auto-generate-sql --auto-generate-sql-add-autoincrement --engine=myisam,innodb --number-of-queries=10 --create-schema=test -uroot -p
注意:测试结果不唯一,但按相对应大多数情况下,一般mysiam适合读数据,innodb适合写数据,但如果是读写都需要的话,还是innodb引擎占大多数使用
SQL语句分析
影响服务器性能的几个方面
- 服务器硬件
- 服务器的操作系统
- 数据库存储引擎的选择
- 数据库参数配置
- 数据库结构设计和SQL语句
SQL性能下降原因
- 查询语句写的不好
- 索引失效
- 关联查询太多join
- 服务器调优及各个参数设置
MySQL常见瓶颈
- CPU:CPU在饱和的时候一般发生在数据装入内存或从磁盘读取数据的时候
- IO :磁盘I/O瓶颈发生在装入数据远大于内存容量的时候
- 服务器硬件的性能瓶颈
explain分析SQL语句
explain是什么?
- 使用explain关键字可以模拟优化器执行SQL查询语句,从而知道MySQL是如何你的SQL语句的
explain能干什么?
- 表的读取顺序
- 数据读取操作的操作类型
- 那些索引可以使用
- 那些索引被实际使用
- 表之间的引用
- 每张表有多少行被优化器查询
explain使用
explain + SQL语句
explain字段解释
id表的读取顺序
- select查询的顺序号,包含一组数字,表示查询中执行select子句或操作表的顺序
两种情况
- id相同,执行顺序由上至下
- id不同,如果是子查询,id的序号会递增,id值越大优先级越高
select_type
- 数据读取操作的操作类型
值 | 描述 |
---|---|
SIMPLE | 简单的select语句(不包括UNION操作或子查询操作) |
PRIMARY | 查询中最外层的SELECT(如两表做UNION或者存在子查询的外层的表操作为PRIMARY,内存的操作为UNION) |
UNION | UNION操作中,查询中处于内层的SELECT,即被union的SELECT |
DERIVED | 表示包含在From子句中的select查询 |
UNION RESULT | union的结果,此时id为NULL |
table
- 显示这一行的数据时关于的那张表
partitions
- 查询访问的分区
type
当我们SQL语句进行优化时,就可以看这个type
排序
system > const > eq_ref > ref > range > index > ALL
- system : 表只有一行记录(等于系统表),这是const类型特例
- const : 表示通过索引一次就找到了,const用于比较primary key
- eq_ref : 唯一索引扫描,对于每个索引键,表中只有一条记录与之匹配
- ref : 非唯一性索引扫描,返回匹配某个单独值所有行,本质上也是一种索引访问,它返回所有匹配某个单独值的行
- range : 只检索给定范围的行,使用一个索引来选择行
- index : 只检索给定范围的行,使用一个索引来选择行
- all : 将遍历全表找到匹配的行
-- 分析查询系统表
explain select * from sys.version;-- 创表测试
create table if not exists test_orm(id int primary key auto_increment not null, name varchar(10));-- 插表
insert into test_orm(name) values ('Small-J');-- 分析表-- type为all
explain select * from test_orm;-- 分析表。 type为const
-- type : const,相当于通过索引一次就可以找到了
explain select * from test_orm where id=1;
possible_keys
- 显示可能应用在这张表中的索引,一个或多个
key
- 实际使用的索引。如果为null,则没有使用索引
- 查询中若使用了覆盖索引,则索引仅出现在key列表中
key_len
- 表示索引中使用的字节数,可通过该列计算查询中使用的索引长度。在不损失精确性的情况下,长度越短越好
- Key_len : 显示的值为索引字段的最大可能长度,并非实际使用长度,即key_len是根据表定义计算而得,不是通过表内检索出的
索引长度计算
varchr(24)变长字段且允许NULL
24*(Character Set:utf8=3,gbk=2,latin1=1)+1(NULL)+2(变长字段)varchr(10)变长字段且不允许NULL
10*(Character Set:utf8=3,gbk=2,latin1=1)+2(变长字段)char(10)固定字段且允许NULL
10*(Character Set:utf8=3,gbk=2,latin1=1)+1(NULL)char(10)固定字段且不允许NULL
10*(Character Set:utf8=3,gbk=2,latin1=1)
ref
- 显示索引那一列被使用到了
rows
- 根据表统计信息及索引选用情况,大致估算出找所需的记录所需要读取的行数
Extra
包含不适合在其他列中显示但十分重要的额外信息
- Using filesort : 说明mysql会对数据使用一个外部的索引排序,而不是按照表内的索引顺序进行读取,MySQL中无法利用索引完成的排序操作称之为“文件排序”
- Using temporary : 使用临时表保存中间结果,MySQL在对查询结果排序时使用临时表
- Using index : 使用了索引,避免了全表扫描
- Using where : 使用了where过滤
- Using join buffer : 使用了连接缓存
- Impossible where : 不可能的条件,where子句的值总是false
注意:当出现Using temporary、Using join buffer我们就需要进行数据优化
Show Profile进行SQL分析
- 是MySQL提供可以用来分析当前会话中语句执行的资源消耗情况,可以用于SQL的调优的测量
- 默认情况下,参数处于关闭状态,并保持最近15次的运行结果。
Show Profile分析步骤
- 是否支持,看看当前MySQL版本是否支持
- 开启功能,默认是关闭,使用前需要开启
-- 查看是否支持开启,默认是什么情况
show variables like 'profiling';-- 设置开启
set profiling = on;-- 查看结果
show profile
type
- all : 显示所有的开销信息
- block io : 显示块IO相关开销
- cpu : 显示CPU相关开销信息
- pic : 显示发送和接收相关开销信息
- memory : 显示内存相关开销信息
- Page faults : 显示页面错误相关开销信息
-- 查看结果
show profie-- 查询对应的
show profile all for query 查看的id号
参数注意
converting HEAP to MyISAM查询结果太大,内存都不够用了往磁盘上搬Creating tmp table 创建临时表Copying to tmp table on disk 把内存中临时表复制到磁盘,危险locked
全局查询日志
- 开启命令
set global general_log = on;
- 将SQL语句写到表里
set global log_output = 'TABLE'
- 你所编写的SQL语句,会记录到MySQL库里的genral_log表
select * from mysql.general_log;
trace分析SQL优化器
trace分析SQL优化器介绍
- 从 MySQL 5.6 开始,可以使用 trace 查看优化器如何选择执行计划。
- 通过trace,能够进一步了解为什么优化器选择A执行计划而不是选择B执行计划,或者知道某个排序使用的排序模式,帮助我们更好地理解优化器行为。
使用trace进行分析
set session optimizer_trace="enabled=on",end_markers_in_json=on;
- optimizer_trace=“enable=on” : 表示开启trace
- end_markers_in_json = on :表示JSON输出开启结束标记
QUERY: select * from t1 where a >900 and b > 910 order by a --SQL语句
TRACE: {"steps": [{"join_preparation": { --SQL准备阶段"select#": 1,"steps": [{"expanded_query": "/* select#1 */ select `t1`.`id` AS `id`,`t1`.`a` AS `a`,`t1`.`b` AS `b`,`t1`.`create_time` AS `create_time`,`t1`.`update_time` AS `update_time` from `t1` where ((`t1`.`a` > 900) and (`t1`.`b` > 910)) order by `t1`.`a`"}] /* steps */} /* join_preparation */},{"join_optimization": { --SQL优化阶段"select#": 1,"steps": [{"condition_processing": { --条件处理"condition": "WHERE","original_condition": "((`t1`.`a` > 900) and (`t1`.`b` > 910))", --原始条件"steps": [{"transformation": "equality_propagation","resulting_condition": "((`t1`.`a` > 900) and (`t1`.`b` > 910))" --等值传递转换},{"transformation": "constant_propagation","resulting_condition": "((`t1`.`a` > 900) and (`t1`.`b` > 910))" --常量传递转换},{"transformation": "trivial_condition_removal","resulting_condition": "((`t1`.`a` > 900) and (`t1`.`b` > 910))" --去除没有的条件后的结构}] /* steps */} /* condition_processing */},{"substitute_generated_columns": {} /* substitute_generated_columns */ --替换虚拟生成列},{"table_dependencies": [ --表依赖详情{"table": "`t1`","row_may_be_null": false,"map_bit": 0,"depends_on_map_bits": [] /* depends_on_map_bits */}] /* table_dependencies */},{"ref_optimizer_key_uses": [] /* ref_optimizer_key_uses */},{"rows_estimation": [ --预估表的访问成本{"table": "`t1`","range_analysis": {"table_scan": {"rows": 1000, --扫描行数"cost": 207.1 --成本} /* table_scan */,"potential_range_indexes": [ --分析可能使用的索引{"index": "PRIMARY","usable": false, --为false,说明主键索引不可用"cause": "not_applicable"},{"index": "idx_a", --可能使用索引idx_a"usable": true,"key_parts": ["a","id"] /* key_parts */},{"index": "idx_b", --可能使用索引idx_b"usable": true,"key_parts": ["b","id"] /* key_parts */}] /* potential_range_indexes */,"setup_range_conditions": [] /* setup_range_conditions */,"group_index_range": {"chosen": false,"cause": "not_group_by_or_distinct"} /* group_index_range */,"analyzing_range_alternatives": { --分析各索引的成本"range_scan_alternatives": [{"index": "idx_a", --使用索引idx_a的成本"ranges": ["900 < a" --使用索引idx_a的范围] /* ranges */,"index_dives_for_eq_ranges": true, --是否使用index dive(详细描述请看下方的知识扩展)"rowid_ordered": false, --使用该索引获取的记录是否按照主键排序"using_mrr": false, --是否使用mrr"index_only": false, --是否使用覆盖索引"rows": 100, --使用该索引获取的记录数"cost": 121.01, --使用该索引的成本"chosen": true --可能选择该索引},{"index": "idx_b", --使用索引idx_b的成本"ranges": ["910 < b"] /* ranges */,"index_dives_for_eq_ranges": true,"rowid_ordered": false,"using_mrr": false,"index_only": false,"rows": 90,"cost": 109.01,"chosen": true --也可能选择该索引}] /* range_scan_alternatives */,"analyzing_roworder_intersect": { --分析使用索引合并的成本"usable": false,"cause": "too_few_roworder_scans"} /* analyzing_roworder_intersect */} /* analyzing_range_alternatives */,"chosen_range_access_summary": { --确认最优方法"range_access_plan": {"type": "range_scan","index": "idx_b","rows": 90,"ranges": ["910 < b"] /* ranges */} /* range_access_plan */,"rows_for_plan": 90,"cost_for_plan": 109.01,"chosen": true} /* chosen_range_access_summary */} /* range_analysis */}] /* rows_estimation */},{"considered_execution_plans": [ --考虑的执行计划{"plan_prefix": [] /* plan_prefix */,"table": "`t1`","best_access_path": { --最优的访问路径"considered_access_paths": [ --决定的访问路径{"rows_to_scan": 90, --扫描的行数"access_type": "range", --访问类型:为range"range_details": {"used_index": "idx_b" --使用的索引为:idx_b} /* range_details */,"resulting_rows": 90, --结果行数"cost": 127.01, --成本"chosen": true, --确定选择"use_tmp_table": true}] /* considered_access_paths */} /* best_access_path */,"condition_filtering_pct": 100,"rows_for_plan": 90,"cost_for_plan": 127.01,"sort_cost": 90,"new_cost_for_plan": 217.01,"chosen": true}] /* considered_execution_plans */},{"attaching_conditions_to_tables": { --尝试添加一些其他的查询条件"original_condition": "((`t1`.`a` > 900) and (`t1`.`b` > 910))","attached_conditions_computation": [] /* attached_conditions_computation */,"attached_conditions_summary": [{"table": "`t1`","attached": "((`t1`.`a` > 900) and (`t1`.`b` > 910))"}] /* attached_conditions_summary */} /* attaching_conditions_to_tables */},{"clause_processing": {"clause": "ORDER BY","original_clause": "`t1`.`a`","items": [{"item": "`t1`.`a`"}] /* items */,"resulting_clause_is_simple": true,"resulting_clause": "`t1`.`a`"} /* clause_processing */},{"reconsidering_access_paths_for_index_ordering": {"clause": "ORDER BY","index_order_summary": {"table": "`t1`","index_provides_order": false,"order_direction": "undefined","index": "idx_b","plan_changed": false} /* index_order_summary */} /* reconsidering_access_paths_for_index_ordering */},{"refine_plan": [ --改进的执行计划{"table": "`t1`","pushed_index_condition": "(`t1`.`b` > 910)","table_condition_attached": "(`t1`.`a` > 900)"}] /* refine_plan */}] /* steps */} /* join_optimization */},{"join_execution": { --SQL执行阶段"select#": 1,"steps": [{"filesort_information": [{"direction": "asc","table": "`t1`","field": "a"}] /* filesort_information */,"filesort_priority_queue_optimization": {"usable": false, --未使用优先队列优化排序"cause": "not applicable (no LIMIT)" --未使用优先队列排序的原因是没有limit} /* filesort_priority_queue_optimization */,"filesort_execution": [] /* filesort_execution */,"filesort_summary": { --排序详情"rows": 90,"examined_rows": 90, --参与排序的行数"number_of_tmp_files": 0, --排序过程中使用的临时文件数"sort_buffer_size": 115056,"sort_mode": "<sort_key, additional_fields>" --排序模式(详解请看下方知识扩展)} /* filesort_summary */}] /* steps */} /* join_execution */}] /* steps */
}
MISSING_BYTES_BEYOND_MAX_MEM_SIZE: 0 --该字段表示分析过程丢弃的文本字节大小,本例为0,说明没丢弃任何文本INSUFFICIENT_PRIVILEGES: 0 --查看trace的权限是否不足,0表示有权限查看trace详情
1 row in set (0.00 sec)
- 关闭trace
set session optimizer_trace = "enabled=off";
TRACE 字段中整个文本大致分为三个过程。
- 准备阶段:对应文本中的 join_preparation
- 优化阶段:对应文本中的 join_optimization
- 执行阶段: 对应文本中的 join_execution
使用时,重点关注优化阶段和执行阶段。
在 trace 结果的 analyzing_range_alternatives 这一项可以看到:使用索引 idx_a 的成本为 121.01,使用索引 idx_b 的成本为 109.01,显然使用索引 idx_b 的成本要低些,因此优化器选择了 idx_b 索引
总结
- explain:获取 MySQL 中 SQL 语句的执行计划,比如语句是否使用了关联查询、是否使用了索引、扫描行数等;
- trace:查看优化器如何选择执行计划,获取每个可能的索引选择的代价。
MySQ5.7数据库-基准测试SQL语句分析相关推荐
- MySQL数据库:SQL语句
MySql数据库系列阅读 MySQL数据库 MySQL数据库:SQL语句 MySQL数据库:完整性约束 MySQL数据库备份与还原 MySQL数据库:编码 1. SQL概述 1.1 什么是SQL SQ ...
- sqlserver 抓取所有执行语句 SQL语句分析 死锁 抓取
sqlserver 抓取所有执行语句 SQL语句分析 死锁 抓取 原文:sqlserver 抓取所有执行语句 SQL语句分析 死锁 抓取 在多人开发中最头疼的是人少事多没有时间进行codereview ...
- JavaWeb学习笔记(数据库、SQL语句、数据查询语法、完整性约束、编码、备份和恢复数据、多表查询)
数据库.SQL语句.数据查询语法.完整性约束.编码.备份和恢复数据.多表查询 JavaWeb学习笔记 数据库 数据库概念 基本命令 启动和关闭mysql服务器 客户端登录退出mysql SQL语句 S ...
- [数据库]简单SQL语句总结
1.在查询结果中显示列名: a.用as关键字:select name as '姓名' from students order by age b.直接表示:select name '姓名' fr ...
- 总结一些关于操作数据库是sql语句还是存储过程问题
总结一些关于操作数据库是sql语句还是存储过程问题 程序中,你跟数据的交互,需要向数据库拿数据.更改数据库的数据等,这些操作,本身不是程序完成的,而是程序发命令给数据库去做的,不管是通过sql语句方式 ...
- 数据库基本----SQL语句大全
数据库基本SQL语句大全 一.基础 1.说明:创建数据库 Create DATABASE database-name 2.说明:删除数据库 drop database dbname 3.说明:备份sq ...
- php 登陆 sql语句,PHP 连接MySQL数据库的SQL语句的简单示例
这篇文章主要为大家详细介绍了PHP 连接MySQL数据库的SQL语句的简单示例,具有一定的参考价值,可以用来参考一下. 首先用phpmyadmin进入建立数据库user 再建个三段的表admin 再别 ...
- 查看创建数据库的sql语句
-- 查看创建数据库的sql语句 #SHOW CREATE DATABASE 数据库名; SHOW CREATE DATABASE db2; -- 修改数据库编码 #语法 ALTER DATABAS ...
- 1.MySQL数据库 2.SQL语句
01数据库概念 * A: 什么是数据库数据库就是存储数据的仓库,其本质是一个文件系统,数据按照特定的格式将数据存储起来,用户可以对数据库中的数据进行增加,修改,删除及查询操作. * B: 什么是数据库 ...
最新文章
- Java web 环境搭建-Linux
- 解决jquery的多次绑定事件
- windows主机防护
- Eigen入门之密集矩阵 4 - 块操作
- django中FastDFS客户端与自定义文件存储系统
- leetcode 697. 数组的度(hashmap)
- python for while enumerate
- Magisk —— 安卓新一代的第三方拓展,systemless模式
- Html 小插件4 百度搜索代码
- oracle补丁类型
- tensorflow应用问题记录
- ZKTeco/熵基科技F18指纹门禁考勤一体机 破解管理员
- 我的团长我的团第四十集
- Editor: 维护一个整数编辑器 HDOJ4699
- attention机制及self-attention(transformer)
- 用python玩转数据测试与作业_用python玩转数据-实验5
- 线性代数让我想想:三阶行列式计算优化策略
- 程序模拟网易163邮箱注册帮助文档
- 企查查爬虫python实现(二)报错与细节
- 奔跑吧!Android虚拟机!Genymotion的安装和配置