MySQL 如何优化慢查询?

news2024/11/20 14:27:21

一、前言

在日常开发中,我们往往会给表加各种索引,来提高 MySQL 的检索效率。
但我们有时会遇到明明给字段加了索引,并没有走索引的Case。 进而导致 MySQL 产生慢查询。
严重场景下,甚至出现主从延迟、数据库拖垮的极端事故。

本文梳理出索引失效的几种常见场景给大家参考。

二、技术基础

Explain 命令使用

只要我们在 SQL 前加上 explain,就可以分析出,当前环境下 MySQL 的“查询方式”以及“索引选择”。

首先大致看下每个字段的含义:

列名含义
id每个select操作的唯一标识
select_type查询的类型,我们可以根据该字段判断查询的性质,包括查询是简单/复杂查询类型
table查询访问表的别名
type关联的类型,mysql把查询过程都视为关联,不管是单表/多表。这个字段也是衡量查询性能的关键字段之一
possible_keys查询可能会使用哪些索引,这列是基于查询访问的列来判断的
keymysql最终决定使用哪个索引(这个索引不一定出现在possible_keys中)
key_lenmysql在索引里使用的字节数,我们可以根据它推断具体使用了索引中的哪些字段
ref查找所用的列/常量
rowsmysql估算的预计扫描行数,这个数字和实际扫描的行数可能相差甚远,包括limit语句对于这个估算值也是不起作用的
filtered表里符合条件的记录数的百分比的估计,我们可以用这个字段大致估计表关联时关联的记录数
extra包含一些额外信息,也是我们优化时需要重点关注的字段

Type(重点看)

type 列表示了 MySQL 关联的类型,它代表了mysql是如何在表里找数据的。

下面按性能从高到低的顺序介绍type类型: 以下四种类型,说明 “性能很好,一般无需优化”

  • system:表里就一条数据
  • const:一般是针对主键/唯一键的等值查询,mysql可以把这类查询优化为一个常量表达式
  • eq_ref:一般出现在多表join时,针对主键/唯一键的等值查询,mysql知道只需要返回一条记录
  • ref:多表 join 时,针对索引字段的查询

以下几种类型,需要 “看具体情况,决定是否要优化”

  • fulltext:关联使用了全文索引
  • ref_or_null:查询走了索引,但是除此之外还要判断字段是不是null,如果出现这种类型,可以考虑这个字段是否有为空的必要
  • index_merge:使用了索引合并优化,如果高频出现,可以考虑是不是索引设计有问题。
  • unique_subquery:in 子句中的子查询,如果只访问主键/唯一键可能会出现这种 type,并不常见
  • index_subquery:同样是 in 里的子查询,访问了索引列,并不常见
  • range:对索引字段的范围扫描,一般出现在带有比较的查询语句中,一些in和or的查询也会导致这种类型的扫描

以下两种类型,需要 “优化 & 避免出现”

  • index:按索引进行全表扫描,如果查询不是覆盖索引的,可能会产生很大量的随机IO
  • all:全表扫描

三、准备工作

  1. 建一张 user
CREATE TABLE `user` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
  `user_id` bigint(20) NOT NULL COMMENT '用户uuid',
  `user_name` varchar(64) DEFAULT '' COMMENT '用户昵称',
  `email` varchar(64) DEFAULT '' COMMENT '邮箱',
  `age` tinyint(4) DEFAULT '1' COMMENT '年龄',
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建日期',
  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新日期',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_userid` (`user_id`),
  KEY `idx_username_email_age` (`user_name`,`email`,`age`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';
复制代码
  1. 初始化一些数据
-- 创建存储过程
delimiter $

CREATE PROCEDURE insert_user(IN limit_num int)
BEGIN
 DECLARE i INT DEFAULT 10;
    DECLARE user_id bigint(20) ;
    DECLARE username varchar(64) ;
    DECLARE email varchar(64) ;    
    DECLARE age TINYINT(4) DEFAULT 1;
    WHILE i < limit_num DO
        SET user_id =  FLOOR(RAND() * 100000000);
        SET username = CONCAT("647-",i);
        SET email = CONCAT(username,"@163.com");
        SET age = FLOOR(RAND() * 100);
        INSERT INTO `user` VALUES (NULL, user_id, username, email, age, NOW(), NOW());
        SET i = i + 1;
    END WHILE;

END $
-- 调用存储过程
call insert_user(100);
复制代码

四、几种常见的索引失效场景

1. 联合索引不满足最左匹配原则

  • 错误示例:
explain select * from user where age = 20 and email = "647@163.com";
复制代码
  • 分析结果:

  • 优化思路:

根据业务场景,合理的建立相应的联合索引。

2. 范围查询,数量级过大,默认走全表扫描

一般来说,MySQL 判断数量级返回超过全数的 10% ~ 30%(或者达到某个阈值),默认会走全表扫描。

  • 错误示例:
explain select * from user where user_id > 10;
复制代码
  • 分析结果:

  • 产生原因:MySQL 优化器判断走索引&回表带来的消耗,比走全表还要多。因此,会走全表扫描。

  • 优化思路:

根据业务场景,预估返回数量级。如果数量级过大,可以分批拉取。
反之,可以加 limit 或者 force index 走索引。

3. 索引列参与运算

  • 错误示例:
explain select * from user where id + 1 = 2;
复制代码
  • 分析结果:

  • 优化思路:

不要用数据库做运算,不浪费宝贵的数据库资源。

4. 索引列使用了函数

  • 错误示例:
explain select * from user where SUBSTR(user_id,1,3) = '100';
复制代码
  • 分析结果:

  • 优化思路:

不要用数据库做函数运算,不浪费宝贵的数据库资源。

5. 错误的 like 使用

  • 错误示例:
explain select * from user where user_name like '%00%';
复制代码
  • 分析结果:

  • 优化思路:

严禁使用左%匹配,要用只能用右%匹配。
如果实在有业务场景,可以使用 ES 做。

6. 隐式类型转换

  • 错误示例:
explain select * from user where user_name = 647;
复制代码
  • 分析结果:

user_namevarchar 类型,传入 INT 比较,会产生 INT -> varchar 的隐式类型转换导致索引失效。

  • 特殊 Case:
explain select * from user where user_id = "647";
复制代码
  • 分析结果:

user_idbigint 类型,如果传入字符串比较。虽然产生隐式转换,但不会导致索引失效。

  • 优化思路:

注意字段类型,避免隐式转换。

7. OR 使用不当

  • 错误示例:
explain select * from user where user_name = "647" or email = "647@163.com";
复制代码
  • 分析结果:

  • 优化思路:

确保 or 的两边都要有索引。

8. 两个索引列做比较

  • 错误示例:
explain select * from user where user_id > id;
复制代码
  • 分析结果:

  • 优化思路:

不要对两个列做比较。

9. 非主键列,加上 not,索引失效

in 会走索引,not in 不会走索引 exists 会走索引,not exists 不会走索引 is null 会走索引,is not null 不会走索引

  • 错误示例:
explain select * from user where user_id not in (647)
复制代码
  • 分析结果:

  • 优化思路:

不要用 not。

10. 非主键列,order by 可能导致索引失效

具体是否失效,和使用的 MySQL 版本也有一定关系。 具体需要根据 explain 分析。

如果 MySQL 版本支持,需要注意满足“最左原则”。

  • 错误示例:
explain select * from user order by user_id;
复制代码
  • 分析结果:

  • 优化思路:

非主键列,尽量不要用 order by。实在要用,需要先用 explain 分析是否可以走索引。
如果条件允许,可以用 ES 代替。

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

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

相关文章

微服务框架 SpringCloud微服务架构 28 数据同步 28.4 发送mq 消息

微服务框架 【SpringCloudRabbitMQDockerRedis搜索分布式&#xff0c;系统详解springcloud微服务技术栈课程|黑马程序员Java微服务】 SpringCloud微服务架构 文章目录微服务框架SpringCloud微服务架构28 数据同步28.4 发送mq 消息28.4.1 直接开干28 数据同步 28.4 发送mq 消…

《Linux运维实战:使用Percona Backup for MongoDB逻辑备份与恢复Mongodb数据》

一、备份与恢复方案 Percona Backup for MongoDB 是一个开源、分布式和低影响的解决方案&#xff0c;用于MongoDB分片集群和副本集的一致备份。从版本1.7.0开始&#xff0c;Percona Backup for MongoDB支持物理和逻辑备份和恢复&#xff0c;仅支持对逻辑备份进行时间点恢复。 …

UIAutomator测试框架介绍

uiautomator简介 UiAutomator是Google提供的用来做安卓自动化测试的一个Java库&#xff0c;基于Accessibility服务。功能很强&#xff0c;可以对第三方App进行测试&#xff0c;获取屏幕上任意一个APP的任意一个控件属性&#xff0c;并对其进行任意操作&#xff0c;但有两个缺点…

软件测试面试笔试习题参考,你都会了吗?

目录 一、 简答题和应用题&#xff1a; 二、 填空题&#xff1a; 三、 判断题&#xff1a; 四、 选择题&#xff1a; 总结 重点&#xff1a;配套学习资料和视频教学 一、 简答题和应用题&#xff1a; 1. 什么是软件测试&#xff1f; 2. 比较软件测试过程和软件开发过程&a…

基于JavaScript中AES和MD5加密,以及简单二维码的生成

一、加密技术 1、对称加密&#xff1a;单密钥加密。一个密钥可以用来加密也可以用来解密 —- AES 2、非对称加密&#xff1a;有两把密码&#xff0c;公钥(用于加密)&#xff0c;私钥(用于解密) 3、摘要算法&#xff1a;把任意长度的输入&#xff0c;根据算法生成一串固定长度…

有环链表入口问题

有环链表入口问题 当快慢指针相遇时&#xff0c;我们可以判断到链表中有环&#xff0c;这时重新设定一个新指针指向链表的起点&#xff0c;且步长与慢指针一样为1&#xff0c;则慢指针与“新”指针相遇的地方就是环的入口。 图片来源:黑马程序员 证明: 设a为起点位置&#xff…

百变郁锦香,开创新典范,深化全球战略布局成就国际高端酒店品质之选

随着消费需求的不断升级&#xff0c;酒店消费场景也进行着多元化的发展&#xff0c;城市高端度假品牌正积极溯源消费需求&#xff0c;寻得品牌文化延伸的可靠路径。同时&#xff0c;各大酒店品牌也加快在市场布局的脚步&#xff0c;希望通过布局城市核心区域获得可持续发展的更…

Python绘制正二十面体

文章目录正二十面体的顶点绘制棱绘制面正二十面体的顶点 正20面体的12个顶点刚好可以分为三组&#xff0c;每一组都是一个符合黄金分割比例的长方形&#xff0c;而且这三个长方形是互相正交的。 所以&#xff0c;想绘制一个正二十面体是比较容易的 import numpy as np from …

大环配体配合物1407166-70-4,NODA-GA-NHS ester,NODA-GA-NHS 酯

●外观以及性质&#xff1a; NODA-GA-NHS ester产物呈固体或粘性液体&#xff0c;取决于PEG分子量&#xff0c;一般为白色固体&#xff0c;双功能大环化合物&#xff0c;大环配体配合物是指由多齿配体与环骨架上的O、N、P、S等多个配位原子形成的环配合物。 NODA-GA-NHS ester …

前端面试题2022-CSS篇

关于前端面试的题&#xff0c;最近整理了一些干货&#xff0c;经常被问到的一些问题&#xff0c;出现频率比较高的问题&#xff0c;如有不足之处&#xff0c;请高调指出&#xff0c;&#xff08;⭐代表难度&#xff0c;星星越多越难&#xff0c;以次类推&#xff09;&#xff0…

如何自动备份指定文件扩展名的文件?

关于文件扩展名 文件扩展名&#xff0c;一个点后跟几个字母&#xff0c;例如“.doc”或“.jpg”&#xff0c;构成计算机文档名称的结尾。保存文档时&#xff0c;请务必在单击“保存”之前输入文档名称和文件扩展名。 自动备份具有特定文件扩展名的文件 随着计算机的使用&…

第十章 鲁棒性检查(中)

文章目录10.5 时钟门控检查(Clock Gating Checks)高电平时钟门控(Active-High Clock Gating)10.5 时钟门控检查(Clock Gating Checks) 当一个门控信号&#xff08;gating signal&#xff09;可以控制逻辑单元中时钟信号&#xff08;clock signal&#xff09;的路径时&#xff…

最近面试遇到的面试题

先挖坑&#xff0c;有空再填坑&#xff01; 迭代器 生成器 常用高阶函数 MySQL 建索引几大原则 浅拷贝 深拷贝 区别 实现 Linux 进程名字 查看进程号 Linux 杀死一个进程 python Linux shell 脚本 数据库 主从复制 配置 nginx 权限设置 python 去除空行 pandas 保留最后一个空…

深入浅出 Swift 中的 some、any 关键字以及主关联类型(primary associated types)

问题现象 从 Swift 5.1 开始,Apple 陆续引入 some、any 关键字,并且从 Swift 5.7 开始对 any 关键字的用法做了增强,并且引入了主关联类型(primary associated types)的概念。 那么它们到底是什么意思?使用它们又能如何改进我们书写代码的范儿呢? 在本篇博文中,您将学…

自动依据你的数据库生成SQL练习题及答案,宝藏软件鉴赏

原创软件不易&#xff0c;方面多点赞、收藏、加关注鼓励&#xff01;后续领更多好用功能&#xff01; 引言 各位好&#xff0c;相信看见这篇文章的朋友&#xff0c;应该也去体验过了chatGPT了吧~&#xff0c;确实chatGPT拉近了我们与未来科技的距离&#xff0c;所有别人火也是…

电脑技巧:Microsoft Edge浏览器技巧介绍

目录 1、导入浏览器数据 2、Edge边栏 3、实用的扩展功能 4、创建集锦列表 4.1 集锦的作用 4.2 使用方法 5、查找优惠券 6、Edge效率省电模式 Microsoft Edge是Windows10操作系统预装的一款非常棒的浏览器和之前的IE不同&#xff0c;采用了谷歌浏览器内核&#xff0c;相…

项目的成功标准如何衡量?【一杯咖啡谈项目】

每个项目经理都想自己的项目能够成功&#xff0c;但是&#xff0c;什么才叫项目的成功&#xff0c;成功的定义是什么&#xff1f;项目成功标准是什么呢&#xff1f; 很多看似失败的项目其实是成功的&#xff0c;很多看似成功的项目其实是失败的。研究项目成功的标准&#xff0…

Chrome 扩展插件:如何开始一个插件的开发

欢迎点击查看个人站首发原文&#xff0c;访问个人站获取更多插件编程知识。 Chrome扩展插件基础是基于前端htmljs开发&#xff0c;然后通过官方提供的项目结构进行开发&#xff0c;需要注意的是&#xff0c;目前Chrome已经支持Manifest V3&#xff0c;FireFox仅仅支持Manifest …

【大数据入门核心技术-Impala】(一)Impala简介

目录 一、Impala介绍 二、Impala优势 三、Impala主要功能 一、Impala介绍 Impala是Cloudera公司主导开发的新型查询系统&#xff0c;它提供SQL语义&#xff0c;能查询存储在Hadoop的HDFS和HBase中的PB级大数据。已有的Hive系统虽然也提供了SQL语义&#xff0c;但由于Hive底层…

代码详细教程+文档+PPT+源码等]SSM框架美妆商城全套|电商购物计算机专业毕业论文java毕业设计网站

&#x1f496;&#x1f496;更多项目资源&#xff0c;最下方联系我们✨✨✨✨✨✨ 目录 Java项目介绍 资料获取 Java项目介绍 计算机毕业设计java毕设之SSM美妆商城项目源码_哔哩哔哩_bilibili项目资料网址: http://itzygogogo.com软件下载地址:http://itzygogogo.com/itsz…