文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

MySQL 如何优化慢查询?

2023-10-08 16:09

关注

一、前言

在日常开发中,我们往往会给表加各种索引,来提高 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类型: 以下四种类型,说明 “性能很好,一般无需优化”

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

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

三、准备工作

  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;复制代码

根据业务场景,预估返回数量级。如果数量级过大,可以分批拉取。
反之,可以加 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 的隐式类型转换导致索引失效。

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 代替。

来源地址:https://blog.csdn.net/m0_71777195/article/details/128249423

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     807人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     351人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     314人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     433人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     221人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-数据库
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯