MySQL学习笔记(6)—— 慢查询日志和索引
文章目录
- 一、 慢查询日志
- 1. MySQL的各种日志
- 2. 认识慢查询日志
- 3. 开启慢查询日志
- 4. 示例
- 二、查询分析器EXPLAIN
- 1. explain简介
- 2. explain的使用
- 3. explain的结果解析
- 三、索引的基本使用
- 1. 什么是索引
- 2. 常见的索引种类
- 3. 索引的使用
- (1)创建索引
- (2)删除索引
- (3)查看索引
- 4. 实战经验
- 5. 示例
- 四、复合索引的前导列特性
- 1. 复合索引前导列特性
- 2. 示例
- 五、覆盖索引
- 1. 如何判断使用了覆盖索引
- 2. 使用索引的示例
一、 慢查询日志
- 在使用mysql的过程中,我们发现系统有时候工作很慢。
- 要想优化这个系统,找到比较慢的sql语句,就要先查日志
1. MySQL的各种日志
- 日志用于记录数据库的运行情况,以及用户对数据库执行的各类操作。
- 当数据库发生故障时,可以根据日志分析和解决问题,从而对数据库进行恢复。
2. 认识慢查询日志
慢查询日志用于记录MySQL数据库中响应时间超过指定阈值(自己设置)的语句。慢查询日志通常也被称之为慢日志,因为它不仅仅只针对
SELECT
语句,像INSERT
、UPDATE
、DELETE
等语句,只要响应时间超过所设定阈值都会记录在慢查询日志中mysql8.0的参数(5.x版本有区别)
3. 开启慢查询日志
开启日志会影响性能
慢查询日志可以通过命令临时设置,也可以修改配置文件永久设置。
语法:
#查看是否开启慢查询日志 show variables like 'slow%';#临时开启慢查询日志 set global slow_query_log='ON'; set global long_query_time=1; #慢查询日志文件所在位置 show variables like '%datadir%';#设置慢开始日志阈值为1s set long_query_time = 1;#查看各日志的阈值 show variables like '%long%';#查看日志输出 show variables like '%log_output%';#查看日志保存位置 show variables like '%datadir%';
4. 示例
# 查看是否开启慢查询日志,看到现在慢开始日志没开,慢开始日志保存位置为D:\programmer\MySQL\..
mysql> show variables like 'slow%';
+---------------------+---------------------------------------------------+
| Variable_name | Value |
+---------------------+---------------------------------------------------+
| slow_launch_time | 2 |
| slow_query_log | OFF |
| slow_query_log_file | D:\programmer\MySQL\Data\7CKJN7W619Q5V0C-slow.log |
+---------------------+---------------------------------------------------+
3 rows in set (0.00 sec)# 开启慢查询日志
mysql> set global slow_query_log='ON';
Query OK, 0 rows affected (0.53 sec)#设置慢开始日志阈值
mysql> set long_query_time = 1;
Query OK, 0 rows affected (0.05 sec)#查看各日志阈值
mysql> show variables like '%long%';
+---------------------------------------------------+----------+
| Variable_name | Value |
+---------------------------------------------------+----------+
| long_query_time | 1.000000 |
| max_long_data_size | 1048576 |
| performance_schema_events_waits_history_long_size | 10000 |
+---------------------------------------------------+----------+
3 rows in set (0.13 sec)#查看日志保存位置,这是所有日志保存的位置
mysql> show variables like '%datadir%';
+---------------+---------------------------+
| Variable_name | Value |
+---------------+---------------------------+
| datadir | D:\programmer\MySQL\Data\ |
+---------------+---------------------------+
1 row in set (0.00 sec)#查看日志输出,看到这是一个表,这个表在mysql用于的管理的数据库mysql中
mysql> show variables like '%log_output%';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| log_output | FILE |
+---------------+-------+
1 row in set (0.00 sec)mysql> use mysql
Database changed
mysql> show tables; #下面查出的slow_log就是慢开始日志输出的表
+---------------------------+
| Tables_in_mysql |
+---------------------------+
| columns_priv |
| db |
| event |
| func |
| general_log |
| help_category |
| help_keyword |
| help_relation |
| help_topic |
| host |
| ndb_binlog_index |
| plugin |
| proc |
| procs_priv |
| proxies_priv |
| servers |
| slow_log |
| tables_priv |
| time_zone |
| time_zone_leap_second |
| time_zone_name |
| time_zone_transition |
| time_zone_transition_type |
| user |
+---------------------------+
24 rows in set (0.32 sec)
下面写两个慢的sql语句,到日志看记录没
mysql> select sleep(3); +----------+ | sleep(3) | +----------+ | 0 | +----------+ 1 row in set (3.37 sec)mysql> select sleep(5); +----------+ | sleep(5) | +----------+ | 0 | +----------+ 1 row in set (5.00 sec)
二、查询分析器EXPLAIN
前面用日志找出慢的sql语句后,可以用
explain
分析问题出在哪里先给出本文中用于演示的数据表:
mysql> select * from employee; +----+--------+------+--------+ | id | name | sex | salary | +----+--------+------+--------+ | 1 | 张三 | 男 | 5500 | | 2 | 李洁 | 女 | 4500 | | 3 | 李小梅 | 女 | 4200 | | 4 | 欧阳辉 | 男 | 7500 | | 5 | 李芳 | 女 | 8500 | | 6 | 张江 | 男 | 6800 | | 7 | 李四 | 男 | 12000 | | 8 | 王五 | 男 | 3600 | | 9 | 马小龙 | 男 | 6000 | | 10 | 龙五 | 男 | 8000 | | 11 | 冯小芳 | 女 | 10000 | | 12 | 马小龙 | 女 | 4000 | +----+--------+------+--------+ 12 rows in set (0.00 sec)
1. explain简介
explain
命令可以查看SQL语句的执行计划。当explain与SQL语句一起使用时,MySQL将显示来自优化器的有关语句执行计划的信息。也就是说,MySQL解释了它将如何处理语句,包括有关如何联接表以及以何种顺序联接表的信息。explain能做什么?
- 分析出表的读取顺序
- 数据读取操作的操作类型
- 哪些索引可以使用
- 哪些索引被实际使用
- 表之间的引用
- 每张表有多少行被优化器查询
2. explain的使用
- explain的使用很简单,只需要在SQL语句之前加上explain命令即可,除
select
语句外,explain
也能分析insert
、update
和delete
语句。(最后加个\G
可以进行规格化显示
)
3. explain的结果解析
参数一览
- 连接类型:
all
是最糟糕的,在表格中越靠左边越好
- 连接类型:
对比where条件不同导致的不同
mysql> explain select * from employee where name = '张三'\G; *************************** 1. row ***************************id: 1select_type: SIMPLEtable: employeetype: ALL possible_keys: NULLkey: NULLkey_len: NULLref: NULLrows: 11Extra: Using where 1 row in set (0.53 sec)mysql> explain select * from employee where id = 1\G; *************************** 1. row ***************************id: 1select_type: SIMPLEtable: employeetype: const possible_keys: PRIMARYkey: PRIMARYkey_len: 4ref: constrows: 1Extra: 1 row in set (0.11 sec)
- 用name做where条件时
- type: ALL (最糟糕)
- key: NULL 没有用索引
- rows: 11 扫描了11行(是全表扫描)
- 用id做where条件时
- type: const 比较好
- key: PRIMARY 用了主键索引
- rows: 1 扫描了1行
- 用name做where条件时
三、索引的基本使用
1. 什么是索引
- 索引是一种特殊的数据结构,类似于图书的目录,它能够极大地提升数据库的查询效率。如果没有索引,在查询数据时必须扫描表中的所有记录才能找出符合条件的记录,这种全表扫描的查询效率非常低
2. 常见的索引种类
索引是对数据库表中一列或多列的值进行排序的一种结构,使用索引可快速访问数据库表中的特定记录
数据库的索引好比一本书的目录,能够加快数据库的查询速度;
索引是快速搜索的关键,如果不加索引,查找任何一条特定的数据都会进行一次全表扫描
常见索引种类
3. 索引的使用
(1)创建索引
# 创建普通索引
CREATE INDEX indexName ON tableName(columnName(length)); # 创建唯一索引
CREATE UNIQUE INDEX indexName ON tableName(columnName(length)); # 创建复合索引
CREATE INDEX indexName ON tableName(columnName1, columnName2, …);
(2)删除索引
DROP INDEX [indexName] ON tableName;
(3)查看索引
SHOW INDEX FROM tableName;
4. 实战经验
-
5. 示例
先对employee查一下有没有索引
mysql> show index from employee\G; *************************** 1. row ***************************Table: employeeNon_unique: 0Key_name: PRIMARYSeq_in_index: 1Column_name: idCollation: ACardinality: 11Sub_part: NULLPacked: NULLNull:Index_type: BTREEComment: Index_comment: 1 row in set (0.00 sec)
- 可见:虽然没有手动建索引,但是有一个主键索引
- 主键会自动建一个索引
现在进行一个没有索引的查询
mysql> explain select * from employee where name = '张三'\G; *************************** 1. row ***************************id: 1select_type: SIMPLEtable: employeetype: ALL possible_keys: NULLkey: NULLkey_len: NULLref: NULLrows: 11Extra: Using where 1 row in set (0.00 sec)
- 可见:key为空,即没有索引,进行了全表扫描
为name字段添加索引
# 建立一个新索引 mysql> CREATE INDEX idx_name ON employee(name); Query OK, 0 rows affected (0.67 sec) Records: 0 Duplicates: 0 Warnings: 0mysql> show index from employee\G; *************************** 1. row ***************************Table: employeeNon_unique: 0Key_name: PRIMARYSeq_in_index: 1Column_name: idCollation: ACardinality: 11Sub_part: NULLPacked: NULLNull:Index_type: BTREEComment: Index_comment: *************************** 2. row ***************************Table: employeeNon_unique: 1Key_name: idx_nameSeq_in_index: 1Column_name: nameCollation: ACardinality: 11Sub_part: NULLPacked: NULLNull: YESIndex_type: BTREEComment: Index_comment: 2 rows in set (0.00 sec)
在进行一次字段的查询
mysql> explain select * from employee where name = '张三'\G; *************************** 1. row ***************************id: 1select_type: SIMPLEtable: employeetype: ref possible_keys: idx_namekey: idx_namekey_len: 93ref: constrows: 1Extra: Using where 1 row in set (0.00 sec)
- 可见:现在用idx_name作为索引进行查询,只扫描1行
删除刚刚建立的索引
mysql> DROP INDEX idx_name ON employee; Query OK, 0 rows affected (0.67 sec) Records: 0 Duplicates: 0 Warnings: 0
四、复合索引的前导列特性
1. 复合索引前导列特性
复合索引前导列特性:创建复合索引
(name, salary, dept)
,相当于创建了三个索引(name, salary, dept)
(name, salary)
(name)
因此在创建复合索引时应该将最常用作查询条件的列放在最左边,依次递减
只建立上述复合索引的话
以下查询都不会使用到索引
select * from employee where salary=8800; select * from employee where dept='部门A'; select * from employee where salary=8800 and dept='部门A';
以下查询会使用到索引
select * from employee where name='liufeng'; select * from employee where name='liufeng' and salary=8800; select * from employee where name='liufeng' and salary=8800 and dept='部门';
2. 示例
# 创建一个复合索引(name,salary,dept)
mysql> create index idx_name_salary_dept on employee(name,salary,dept);
Query OK, 0 rows affected (0.62 sec)
Records: 0 Duplicates: 0 Warnings: 0# 查询name(可见用索引)
mysql> explain select * from employee where name='张三'\G;
*************************** 1. row ***************************id: 1select_type: SIMPLEtable: employeetype: ref
possible_keys: idx_name_salary_deptkey: idx_name_salary_deptkey_len: 93ref: constrows: 1Extra: Using where
1 row in set (0.00 sec)# 查询name ane dept(可见用索引)
mysql> explain select * from employee where name='张三' and dept = 'A'\G;
*************************** 1. row ***************************id: 1select_type: SIMPLEtable: employeetype: ref
possible_keys: idx_name_salary_deptkey: idx_name_salary_deptkey_len: 93ref: constrows: 1Extra: Using where
1 row in set (0.00 sec)# 查询dept(可见没有索引)
mysql> explain select * from employee where dept = 'A'\G;
*************************** 1. row ***************************id: 1select_type: SIMPLEtable: employeetype: ALL
possible_keys: NULLkey: NULLkey_len: NULLref: NULLrows: 11Extra: Using where
1 row in set (0.00 sec)
五、覆盖索引
覆盖索引又称之为索引覆盖,即select的数据列只从索引中就能得到,不必读取数据行,也就是只需扫描索引就可以得到查询结果
这就好像:要查看的数据就在书的目录里,看看目录就可以了,不用真正去翻书
关于覆盖索引的几点说明:
使用覆盖索引,只需要从索引中就能检索到需要的数据,而不要再扫描数据表;
索引的体量往往要比数据表小很多,因此只读取索引速度会非常快,也会极大减少数据访问量;
MySQL的查询优化器会在执行查询前判断,是否有一个索引可以覆盖所有的查询列;
并非所有类型的索引都可以作为覆盖索引,覆盖索引必须要存储索引列的值。像哈希索引、空间索引、全文索引等并不会真正存储索引列的值
1. 如何判断使用了覆盖索引
- 当一个查询使用了覆盖索引,在查询分析器EXPLAIN的Extra列可以看到
Using index
2. 使用索引的示例
创建复合索引
(name, salary, dept)
mysql> show index from employee\G; *************************** 1. row ***************************Table: employeeNon_unique: 0Key_name: PRIMARYSeq_in_index: 1Column_name: idCollation: ACardinality: 11Sub_part: NULLPacked: NULLNull:Index_type: BTREEComment: Index_comment: *************************** 2. row ***************************Table: employeeNon_unique: 1Key_name: idx_name_salary_deptSeq_in_index: 1Column_name: nameCollation: ACardinality: 11Sub_part: NULLPacked: NULLNull: YESIndex_type: BTREEComment: Index_comment: *************************** 3. row ***************************Table: employeeNon_unique: 1Key_name: idx_name_salary_deptSeq_in_index: 2Column_name: salaryCollation: ACardinality: 11Sub_part: NULLPacked: NULLNull: YESIndex_type: BTREEComment: Index_comment: *************************** 4. row ***************************Table: employeeNon_unique: 1Key_name: idx_name_salary_deptSeq_in_index: 3Column_name: deptCollation: ACardinality: 11Sub_part: NULLPacked: NULLNull: YESIndex_type: BTREEComment: Index_comment: 4 rows in set (0.00 sec)
- 由于复合索引的前导列特性,多建立了三个索引
使用覆盖索引(注意查询的列信息必须能从索引中获得)
# 使用了覆盖索引 mysql> explain select id from employee\G; *************************** 1. row ***************************id: 1select_type: SIMPLEtable: employeetype: index possible_keys: NULLkey: idx_name_salary_deptkey_len: 191ref: NULLrows: 11Extra: Using index 1 row in set (0.34 sec)# 使用了覆盖索引 mysql> explain select id from employee\G; *************************** 1. row ***************************id: 1select_type: SIMPLEtable: employeetype: index possible_keys: NULLkey: idx_name_salary_deptkey_len: 191ref: NULLrows: 11Extra: Using index 1 row in set (0.34 sec)# 多了一个sex字段,索引没有覆盖,这个只能全表扫描了 mysql> explain select id from employee\G; *************************** 1. row ***************************id: 1select_type: SIMPLEtable: employeetype: index possible_keys: NULLkey: idx_name_salary_deptkey_len: 191ref: NULLrows: 11Extra: Using index 1 row in set (0.34 sec)
MySQL学习笔记(6)—— 慢查询日志和索引相关推荐
- MySQL学习笔记(三)查询
写在前面:本篇为作者自学总结,学习内容为课堂所学和网络学习笔记汇总,对于内容引用部分在文中和文末注明. 文章仅供参考,如需深入了解,请查阅MySQL参考手册.附上下载链接: 链接:https://pa ...
- mysql 学习笔记 多表查询02
把一张表 想象成两张表,进行多表查询 举例: 查询 所有员工的 姓名 以及 其 上级姓名 select s1.stname, s2.stname from staff as s1, staff as ...
- MySQL学习笔记——多表查询
目录 一.多表查询 1.多表查询的实现 1.1 出现笛卡尔积的错误 1.2 多表查询的正确方式,需要有连接条件 2.多表查询的分类 2.1 等值连接vs非等值连接 2.2 自连接vs非自连接 2.3 ...
- mysql学习笔记之连接查询与子查询
mysql连接查询与子查询 1.子查询是指在另一个查询语句中的SELECT子句. 例句: SELECT * FROM t1 WHERE column1 = (SELECT column1 FROM t ...
- MySQL学习笔记-03高级查询、多表联合查询、聚合函数、子查询、视图、存储过程、权限、
关于作者 金山老师:从事Java.大数据.Python职业化培训6年,项目管理.软件开发14年.欢迎添加我的微信号[jshand],最近建了一些微信交流群,扫描下方二维码添加公众号,回复:进群 文章目 ...
- MySQL学习笔记:等值查询、范围查询、死锁、间隙锁的本质
环境 MySQL:5.7.26-log 前言 答疑文章(二):用动态的观点看加锁 原则 1:加锁的基本单位是 next-key lock.希望你还记得,next-key lock 是前开后闭区间. 原 ...
- MySQL学习笔记5||数据查询select
备注:该博客内容根据技术教学视频整理与总结而成,原视频来自于尚硅谷MySQL教程. 一.基础查询 select from 语法: SELECT 要查询的东西[FROM 表名]; 特点: ...
- mysql学习笔记之排序查询和函数(进阶四)
USE myemployees; #进阶四:排序查询() /* 语法: select 查询列表 from 表 order by 排序列表[asc|desc]asc升序desc降序,可不写,默认升序 / ...
- mysql 学习笔记15 子查询
子查询定义: 单上子查询举例: 显示与 员工 关平 同一部门的员工, 但不包括关平 select * from staff where staff.stdepno = (select staff.st ...
- MySQL学习笔记 | 模式匹配 模糊查询
目录 LIKE运算符:模式匹配 模糊查询 作业练习 1.查看XSCJ数据库中学生基本情况表(XS)的全部数据信息.(确保数据和教材第105页表5-13一致.) 2.完成教材第106页以下操作: (1) ...
最新文章
- 使用VMware Infrastructure Client中的VMware Server 2.0.x的管理
- phpstudy升级mysql之后,修改配置文件无效的问题
- 网络安全产品 / 相关产品简要说明
- mqtt js 中乱码_mqtt之上RRPC同步调用实战
- Git撤销修改场景及对应指令(checkout、reset、revert)详解
- python 列表解析式_python列表解析式,字典解析式,集合解析式和生成器
- sae 微信 java web_[1] 微信公众号与sae的web应用之间的配置
- 【java】java 并发变成 阶段同步器 Phaser
- PLSQL_案例优化系列_明白索引是如何让SQL运行飞快(案例5)
- JS之形参带默认值的写法代码
- Word与Excel展示Oracle BI Publisher页签
- Mstar的Monitor方案OSD 菜单制作(五)——icon绘制
- js监听浏览器tab页面变化
- 支持向量机是怎么画分类平面的?
- python 拼多多秒杀_干货 | Jmeter 如何保证类似拼多多抢购、秒杀活动正常运行?...
- 「解读」华为云桌面说“流畅”的时候,究竟在说什么?
- 【机器学习基石】机器学习的种类(三)
- Java实战:粒子群算法
- idea工具栏没有vcs被替换成git
- 基于MATLAB读取高光谱影像每个像素的光谱信息
热门文章
- 证券从业资格证Get
- cocos2dx-3.x物理引擎Box2D介绍
- easeus恢复没有手机_使用EaseUS数据恢复向导恢复已删除的数据
- java stax_在Java中使用StAX的代码
- 开发疣猪飞行摇杆A10C(第二章)
- php实现TXT小说章节解析、小说章节在线阅读
- 2021年全球电液伺服阀市场规模大约为104亿元(人民币),预计2028年将达到127亿元
- docker部署python项目_docker部署项目实践
- 阿里云视频点播-URL批量拉取上传(调整为多个视频上传)
- 你不知道的“探探”引流套路,让更多人“喜欢你”!