MySQL索引优化(二)

news2024/11/25 6:40:12

文章目录

  • 一、查询优化
    • 1. 索引失效
      • (1)不满足最左前缀法则,索引失效
      • (2)在索引列上做任何计算、函数操作,索引失效
      • (3)存储引擎使用索引中范围条件右边的列,索引失效
      • (4)Mysql使用不等于时,索引失效
      • (5)is null可以使用索引,但是is not null无法使用索引
      • (6)like以通配符开头,索引失效
      • (7)字符串不加单引号,索引失效
      • (8)使用or连接时,索引失效
      • 小结
    • 2. 排序优化
    • 3. 单表优化
    • 4. 关联查询优化
    • 5. 分组优化
  • 二、慢查询日志
    • 1. 慢查询日志简介
    • 2. 慢查询日志使用

一、查询优化

1. 索引失效

(1)最左前缀法则:如果索引有多列,要遵循最左前缀法则,指的是查询从索引的最左前列开始并且不跳过索引中的列。(针对复合索引)
(2)不在索引列上做任何计算、函数操作,会导致索引失效而转向全表扫描。
(3)存储引擎不能使用索引中范围条件右边的列。
(4)Mysql在使用不等于时无法使用索引,会导致全表扫描。
(5)is null可以使用索引,但是is not null无法使用索引。
(6)like以通配符开头会使索引失效,导致全表扫描。
(7)字符串不加单引号,索引会失效。
(8)使用or连接时,索引失效。

  • 创建表
drop table if exists students;
CREATE TABLE students (
  id INT PRIMARY KEY AUTO_INCREMENT COMMENT "主键id",
  sname VARCHAR (24) COMMENT '学生姓名',
  age INT COMMENT '年龄',
  score INT COMMENT '分数',
	time TIMESTAMP COMMENT '入学时间'
);
 
INSERT INTO students(sname,age,score,time) VALUES('小明',22,100,now());
INSERT INTO students(sname,age,score,time) VALUES('小红',23,80,now());
INSERT INTO students(sname,age,score,time) VALUES('小绿',24,80,now());
INSERT INTO students(sname,age,score,time) VALUES('黑',23,70,now());
  • 创建复合索引
alter table students add index idx_sname_age_score(sname,age,score);

在这里插入图片描述

  • 使用复合索引查询

key_len表示使用索引的字节大小,值越大表示索引使用越充分

explain select * from students where sname="小明" and age = 22 and score = 100;
explain select * from students where sname="小明" and age = 22;
explain select * from students where sname="小明";

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

(1)不满足最左前缀法则,索引失效

explain select * from students where age = 20;

在这里插入图片描述

查询条件是sname、score,中间跳过了age, 所以score没有用到索引,只有sname用到了索引
跟上面单独使用sname查询时的ken_len一样,都是99

explain select * from students where sname="小明" and score = 80;

在这里插入图片描述

(2)在索引列上做任何计算、函数操作,索引失效

-- 不在索引列上做任何计算、函数操作,会导致索引失效而转向全表扫描。
explain select * from students where left(sname,2) = "小明";

在这里插入图片描述

(3)存储引擎使用索引中范围条件右边的列,索引失效

age是范围查找,所以age右边的score列索引失效,ken_len=104说明只有sname、age列索引生效

-- 存储引擎不能使用索引中范围条件右边的列。
explain select * from students where sname="小明" and age > 22 and score = 100;

在这里插入图片描述

(4)Mysql使用不等于时,索引失效

-- Mysql在使用不等于时无法使用索引会导致全表扫描。
explain select * from students where sname != "小明";

在这里插入图片描述

(5)is null可以使用索引,但是is not null无法使用索引

explain select * from students where sname is  null;

在这里插入图片描述

-- is null可以使用索引,但是is not null无法使用索引。
explain select * from students where sname is not null;

在这里插入图片描述

(6)like以通配符开头,索引失效

-- like以通配符开头会使索引失效导致全表扫描。
explain select * from students where sname like "%明";

在这里插入图片描述

(7)字符串不加单引号,索引失效

-- 字符串不加单引号索引会失效。
explain select * from students where sname = 123;

在这里插入图片描述

(8)使用or连接时,索引失效

-- 使用or连接时索引失效。
explain select * from students where sname="小明" or age = 22;

在这里插入图片描述

小结

在这里插入图片描述

建议:
1.对于单值索引,尽量选择针对当前查询字段过滤性更好的索引。
2.对于组合索引,当前where查询中过滤性更好的字段在索引字段顺序中位置越靠前越好。
3.对于组合索引,尽量选择能够包含在当前查询中where子句中更多字段的索引。
4.尽可能通过分析统计信息和调整query的写法来达到选择合适索引的目的。

2. 排序优化

1.尽量避免使用Using FileSort方式排序。
2.order by语句使用索引最左前列或使用where子句与order by子句条件组合满足索引最左前列。
3.where子句中如果出现索引范围查询会导致order by索引失效。

KEY a_b_c(a,b,c)
order by 能使用索引最左前缀
-- ORDER BY a
-- ORDER BY a,b
-- ORDER BY a,b,c
-- ORDER BY a DESC, b DESC, c DESC

如果WHERE使用索引的最左前缀定义为常量,则order by能使用索引
-- WHERE a = CONST ORDER BY b,c 
-- WHERE a = CONST AND b = CONST ORDER BY c 
-- WHERE a = CONST AND b > CONST ORDER BY b,c 

不能使用索引进行排序
-- ORDER BY a ASC, b DESC, c DESC // 排序不一致
-- WHERE g = CONST ORDER BY b,c // 丢失a索引
-- WHERE a = CONST ORDER BY c  // 丢失b索引
-- WHERE a = CONST ORDER BY a,d  // d不是索引的一部分
-- WHERE a in(...) ORDER BY b,c //对于排序来说,多个相等条件也是范围查询

3. 单表优化

  • 建表
-- 单表查询优化
CREATE TABLE IF NOT EXISTS article (
id INT(10) PRIMARY KEY AUTO_INCREMENT,
author_id INT(10) NOT NULL,
category_id INT(10) NOT NULL,
views INT(10) NOT NULL,
comments INT(10) NOT NULL,
title VARBINARY(255) NOT NULL,
content TEXT NOT NULL
);
 
INSERT INTO article(author_id, category_id, views, comments, title, content) VALUES
(1, 1, 1, 1, '1', '1'),
(2, 2, 2, 2, '2', '2'),
(1, 1, 3, 3, '3', '3');
#1.查询category_id为1的,且comments大于1的情况下,views最多的id和author_id的信息
explain select id,author_id 
from article
where category_id=1 and comments>1 order by views desc limit 1;

在这里插入图片描述

#2.建立索引
alter table article add index idx_ccv(category_id,comments,views);
#3.再次测试,comments是范围查询,所以右边views列索引失效
explain select id,author_id 
from article
where category_id=1 and comments>1 order by views desc limit 1;

在这里插入图片描述

#4.重新创建索引
drop index idx_ccv on article;
// comments是范围查询,所以不建立comments复合索引
alter table article add index idx_cv(category_id,views);
#5.再次测试
explain select id,author_id 
from article
where category_id=1 and comments>1 order by views desc limit 1;

在这里插入图片描述

4. 关联查询优化

  • 建表
CREATE TABLE IF NOT EXISTS class (
id INT(10) AUTO_INCREMENT,
card INT(10),
PRIMARY KEY (id)
);
CREATE TABLE IF NOT EXISTS book (
bookid INT(10) AUTO_INCREMENT,
card INT(10),
PRIMARY KEY (bookid)
);
 
INSERT INTO class(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO class(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO class(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO class(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO class(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO class(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO class(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO class(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO class(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO class(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO class(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO class(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO class(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO class(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO class(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO class(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO class(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO class(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO class(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO class(card) VALUES(FLOOR(1 + (RAND() * 20)));
 
INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));
INSERT INTO book(card) VALUES(FLOOR(1 + (RAND() * 20)));

内连接时,mysql会自动把小结果集的表选为驱动表,所以大表的字段最好加上索引。
左外连接时,左表会全表扫描,所以右边大表字段最好加上索引,右外连接同理。
我们最好保证被驱动表上的字段建立了索引。

#1.联表查询
explain select *
from class
left join book
on class.card = book.card;

在这里插入图片描述

#2.建立索引
alter table book add index idx_card(card);
#3.测试
explain select *
from class
left join book
on class.card = book.card;

在这里插入图片描述

5. 分组优化

参照排序优化。

  • 建表
drop table if exists students;
CREATE TABLE students (
  id INT PRIMARY KEY AUTO_INCREMENT COMMENT "主键id",
  sname VARCHAR (24) COMMENT '学生姓名',
  age INT COMMENT '年龄',
  score INT COMMENT '分数',
	time TIMESTAMP COMMENT '入学时间'
);
 
INSERT INTO students(sname,age,score,time) VALUES('小明',22,100,now());
INSERT INTO students(sname,age,score,time) VALUES('小红',23,80,now());
INSERT INTO students(sname,age,score,time) VALUES('小绿',24,80,now());
INSERT INTO students(sname,age,score,time) VALUES('黑',23,70,now());
-- 分组优化
alter table students add index idx_sas(sname,age,score);
#没有WHERE条件,GROUP BY age不满足最左前缀,所以是Using temporary; Using filesort
explain select count(*),sname from students GROUP BY age;

在这里插入图片描述

explain select count(*),sname 
from students 
where sname="小明" and age > 22
GROUP BY score;

在这里插入图片描述

二、慢查询日志

1. 慢查询日志简介

MySQL的慢查询日志是MySQL提供的一种日志记录,用来记录在MySQL中响应时间超过阀值的语句,具体指运行时间超过long_query_time值的SQL,则会被记录到慢查询日志中。可以由它来查看哪些SQL超出了我们最大忍耐时间值。

2. 慢查询日志使用

默认情况下,MySQL数据库没有开启慢查询日志,需要手动设置参数。
查看是否开启:show variables like ‘%slow_query_log%’;
开启日志:set global slow_query_log = 1;
设置时间:set global long_query_time = 1;
查看时间: SHOW VARIABLES LIKE ‘long_query_time%’;
查看超时的sql记录日志:Mysql的数据文件夹下
C:\ProgramData\MySQL\MySQL Server 5.7\Data\设备名称-slow.log
注意:非调优场景下,一般不建议启动该参数,慢查询日志支持将日志记录写入文件,开启慢查询日志或多或少带来一定的性能影响。

-- 慢查询日志
-- 查看是否开启:show variables like '%slow_query_log%';
show variables like '%slow_query_log%';

在这里插入图片描述

-- 开启日志:
set global slow_query_log = 1;
-- 设置时间: 
set global long_query_time = 1;
-- 查看时间: 需要重新开启一个会话才能查看刚设置的时间
SHOW VARIABLES LIKE 'long_query_time%';
  • 需要重新开启一个会话才能查看刚设置的时间,cmd新建连接创建新会话
C:\Users\Administrator>mysql -uroot -p
Enter password: ****
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 7
Server version: 5.7.37-log MySQL Community Server (GPL)

Copyright (c) 2000, 2022, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> SHOW VARIABLES LIKE 'long_query_time%';
+-----------------+----------+
| Variable_name   | Value    |
+-----------------+----------+
| long_query_time | 1.000000 |
+-----------------+----------+
1 row in set, 1 warning (0.00 sec)

mysql>
  • 查询一个有300万数据的表,没有建PAGE索引,耗时超过1s
select * from person where PAGE = 51;

在这里插入图片描述

  • 打开慢查询日志文件
    在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

倪健中会长应邀出席首届世界数贸易博览会致辞:把杭州打造成全球数字贸易元宇宙之都

12月11日至14日,首届全球数字贸易博览会在浙江省杭州市盛大举办。博览会由浙江省人民政府和商务部联合主办,杭州市人民政府、浙江省商务厅和商务部贸发局共同承办,主题为“数字贸易商通全球”,爱尔兰为主宾国,北京、上…

大航海时代:葡萄牙、西班牙率先出发,英国为何成为最大赢家?

欧洲经历了长达千年的中世纪以后,忽然开始自我反省了。为啥?因为打了上千年,不仅社会没进步,反而因为各种瘟疫、战争,把人口搞掉了一大半。 这么玩下去,日耳曼人的各大分支,可能都要完犊子了&a…

基于java+springboot+mybatis+vue+mysql的智能热度分析和自媒体推送平台

项目介绍 前端页面: 功能:首页、文章信息、图片信息、视频信息、个人中心、后台管理 管理员后台管理页面: 功能:首页、个人中心、用户管理、文章类型管理、文章信息管理、图片类型管理、图片信息管理、视频类型管理、视频信息管…

数据工厂刷新PowerBI数据集2

前面已经介绍过数据工厂中刷新PowerBI数据集,我们先发起一个web请示获取了token,然后再把token传入到接口中从而刷新数据集。 但是,明明都是微软家的产品,竟然还需要先获取token?明明Power Apps、Power Automate里都不需要的啊&…

茶文化推广网站

开发工具(eclipse/idea/vscode等): 数据库(sqlite/mysql/sqlserver等): 功能模块(请用文字描述,至少200字): 网型站前台:网站个介绍、帮助信总、茶文化、茶叶分享、讨论信总 管理功能: 1、管理网站介绍、帮…

刚做外贸,先做平台好还是独立站好?

作为亚马逊这样的平台卖家,依托平台完善的第三方服务和流量红利,很容易将产品卖到海外。如今,随着平台要求越来越严格,管理政策越来越多变,用户需求也越来越多样化和苛刻,卖家在平台上经营店铺的一些问题正…

[附源码]Python计算机毕业设计SSM基于Web的摄影爱好者交流社区(程序+LW)

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis Maven Vue 等等组成,B/S模式 M…

Clone使用

实现克隆接口:clone方法是默认是Object的方法 1)这个接口是一个标记性的接口(空接口),他们内部都没有方法和属性,实现这个接口表示这个对象都可以进行克隆,我们调用Object对象的Object.clone()方法,如果没有实现Cloneable的类对象…

【云原生】k8s声明式资源管理

内容预知 1.资源配置清单的管理 1.1 查看资源配置清单 1.2 修改资源配置清单并应用 离线修改 在线修改 1.3 删除资源配置清单 2.自主编写资源清单 2.1 初步认识资源清单中svc的重要配置项 2.2 手动编写 svc资源配置 3.手动生成模板,再编写资源清单 &#x…

解决虚拟机IP地址无法获取和网络无法连接

首先看一下电脑的end33分配成功没有 ifconfig或者使用ip addr查询都可以 ip addr 目录 1.首先看看你的网络连接模式是不是NAT 2.去主机电脑服务查看这四个服务是否开启 3.查看虚拟机子网ip是否分配了 4.修改我们的网卡配置文件,使用下面命令进入文件 5.重启网…

jemeter 压测并生成报告

文章目录前言一、压测步骤1.1 创建jvm文件1.2 压测生成测试文件及html压测结果二、结果分析前言 jmeter:是Apche公司使用Java平台开发的一款测试工具。 一、压测步骤 1.1 创建jvm文件 添加测试计划 (当打开jmeter默认有一个测试计划)添加…

高并发下解决AtomicLong性能瓶颈的方案——LongAdder

一、 LongAdder简介 LongAdder类是JDK1.8新增的一个原子性操作类。上一节说到,AtomicLong通过CAS提供了非阻塞的原子性操作,相比用阻塞算法的synchronized来说性能已经得到了很大提升。在高并发下大量线程会同时竞争更新同一个原子变量,但由…

Qt 模型视图编程之重置模型数据

背景 Qt 模型视图编程中模型定义了标准接口对数据进行访问,可根据需求继承对应的抽象模型类来实现自定义的数据模型。一个基本的数据模型至少要实现以下虚函数: ①.rowCount:行数,返回要显示多少行; ②&…

软件工程---习题六

4. 图6.18给出的程序流程图代表一个非结构化的程序,问:   (1)为什么说它是非结构化的?   答:通常所说的结构化程序,是按照狭义的结构程序的定义衡量,符合定义规定的程序,每个代码…

【操作系统】模式切换篇

CPU的模式 什么是CPU的模式?这和CPU的发展过程有关,最开始CPU是8位的,后来发展到16位,然后是32位,现在是64位,多少多少位指的是寄存器的位宽。CPU能使用的寄存器宽度以及CPU使用的指令等就构成了CPU的模式…

传统ERP管理项目有哪些问题?项目ERP系统哪个好?

8Manage FAS 是专为基于项目的公司设计的企业资源规划系统(ERP系统)。基于项目的公司包括建筑、工程和施工操作 (AEC)、产品要订购制造 (ETO) 和各种其他类型的专业服务公司 (PSO)。 对任何公司来说,无论在什么行业,项目对其业务…

Linux 调试之 TRACE_EVENT

文章目录前言一、TRACE_EVENT简介二、TRACE_EVENT() 结构2.1 TRACE_EVENT简介2.2 trace_sched_switch示例三、The header file参考资料前言 在Linux的整个历史中,人们一直希望在内核中添加静态跟踪点,即记录内核中特定位置的数据以供以后检索的函数。与…

[附源码]Nodejs计算机毕业设计基于大数据的超市进销存预警系统Express(程序+LW)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程。欢迎交流 项目运行 环境配置: Node.js Vscode Mysql5.7 HBuilderXNavicat11VueExpress。 项目技术: Express框架 Node.js Vue 等等组成,B/S模式 Vscode管理前后端分…

开源大数据比对平台(dataCompare)新版本发布

开源大数据比对平台设计与实践—dataCompare 前文介绍了开源大数据比对平台设计和实践,最近将整体业务流程进行了完善和开发。 一、目前当前版本实现了如下功能: (1)低代码简单配置完成数据比对核心功能 (2)数据量级比对、数据一致性比对 二、系统功…

sentinel限流,熔断等具体流程分析

基于sentinel 1.8.6 从sentinel-dashboard来看,sentinel主要提供了流控,熔断,热点,系统规则,授权规则等。 针对http请求的数据监控以及规则限制的适配,可以参考sentinel-spring-webmvc-adapter以及sentin…