架构师系列-MYSQL调优(七)- 索引单表优化案例

news2024/11/14 14:51:29

索引单表优化案例

1. 建表

  • 创建表 插入数据

  • 下面是一张用户通讯表的表结构信息,这张表来源于真实企业的实际项目中,有接近500万条数据.

CREATE TABLE user_contacts (
  id INT(11) NOT NULL AUTO_INCREMENT,
  user_id INT(11) DEFAULT NULL COMMENT '用户标识',
  mobile VARCHAR(50) DEFAULT NULL COMMENT '手机号',
  NAME VARCHAR(20) DEFAULT NULL COMMENT '姓名',
  verson INT(11) NOT NULL DEFAULT '0' COMMENT '版本',
  create_by VARCHAR(64) DEFAULT NULL COMMENT '创建者',
  create_date DATETIME NOT NULL COMMENT '创建时间',
  update_by VARCHAR(64) DEFAULT NULL COMMENT '更新者',
  update_date DATETIME NOT NULL COMMENT '更新时间',
  remarks VARCHAR(255) DEFAULT NULL COMMENT '备注信息',
  del_flag CHAR(1) NOT NULL DEFAULT '0' COMMENT '删除标识',
  PRIMARY KEY (id)
); 

 2. 单表索引分析

需求一

  • 查询所有名字中包含李的用户姓名和手机号,并根据user_id字段排序
SELECT NAME, mobile FROM  user_contacts WHERE NAME LIKE '李%' ORDER BY user_id;
  • 通过explain命令 查看SQL查询优化信息

  • 结论:很显然type是ALL,即最坏情况。Extra里还出现Using filesort(文件内排序,未使用到索引),也是最坏情况,所以优化是必须的。
 优化

1、首先添加联合索引, 该联合索引包含所有要查询的字段,使其成为覆盖索引,一并解决like模糊查询时索引失效问题 。

-- 添加联合索引
ALTER TABLE user_contacts ADD INDEX idx_nmu(NAME,mobile,user_id);

2、进行分析

EXPLAIN SELECT NAME, mobile FROM  user_contacts WHERE NAME LIKE '%李%' ORDER BY user_id;

分析结果显示: type连接类型提升到了index级别,通过索引就获取到了全部数据,但是Extra字段中还是存在 Using filesort.

继续优化: 根根据最佳左前缀法则,之后最左侧列是有序的, 在创建联合索引时,正确的顺序应该是: user_id,NAME,mobile

-- 删除索引
DROP INDEX idx_nmu ON user_contacts 

-- 添加重新排序后的索引
ALTER TABLE user_contacts ADD INDEX idx_unm(user_id,NAME,mobile);

 执行查询,发现type=index , Using filesort没有了.

EXPLAIN SELECT NAME, mobile FROM  user_contacts WHERE NAME LIKE '%李%' ORDER BY user_id;

 需求二

统计手机号是135、136、186、187开头的用户数量.

EXPLAIN  SELECT COUNT(*) FROM user_contacts WHERE mobile LIKE '135%' OR mobile LIKE '136%' OR mobile LIKE '186%' OR mobile LIKE '187%';

type=index : 用到了索引,但是进行了索引全表扫描

key=idx_unm: 使用到了联合索引,但是效果并不是很好

Extra=Using where; Using index: 查询的列被索引覆盖了,但是无法通过该索引直接获取数据.

综合上面的执行计划给出的信息,需要进行优化.

优化

经过上面的分析,发现联合索引没有发挥作用,所以尝试对 mobile字段单独建立索引

ALTER TABLE user_contacts ADD INDEX idx_m(mobile);

再次执行,得到下面的分析结果

EXPLAIN  SELECT COUNT(*) FROM user_contacts WHERE mobile LIKE '135%' OR mobile LIKE '136%' OR mobile LIKE '186%' OR mobile LIKE '187%';

 

type=range: 使用了索引进行范围查询,常见于使用>,>=,<,<=,BETWEEN,IN() 或者 like 等运算符的查询中。

key=idx_m: mysql选择了我们为mobile字段创建的索引,进行数据检索

rows=1575026: 为获取所需数据而进行扫描的行数,比之前减少了近三分之一。

count(*) 和 count(1)和count(列名)区别

进行统计操作时,count中的统计条件可以三种选择:

EXPLAIN  SELECT COUNT(*) FROM user_contacts 
WHERE mobile LIKE '135%' OR mobile LIKE '136%' OR mobile LIKE '186%' OR mobile LIKE '187%';

EXPLAIN  SELECT COUNT(id) FROM user_contacts 
WHERE mobile LIKE '135%' OR mobile LIKE '136%' OR mobile LIKE '186%' OR mobile LIKE '187%';

EXPLAIN  SELECT COUNT(1) FROM user_contacts 
WHERE mobile LIKE '135%' OR mobile LIKE '136%' OR mobile LIKE '186%' OR mobile LIKE '187%';

执行效果:
  count(*) 包括了所有的列,在统计时 不会忽略列值为null的数据.
  count(1) 用1表示代码行,在统计时,不会忽略列值为null的数据.
    count(列名)在统计时,会忽略列值为空的数据,就是说某个字段的值为null时不统计.
执行效率:
  列名为主键, count(列名)会比count(1)快
    列名为不是主键, count(1)会比count(列名)快
    如果表没有主键,count(1)会比count(*)快
    如果表只有一个字段,则count(*) 最优.

需求三

​​​​​​​查询2017-2-16日,新增的用户联系人信息. 查询字段: name , mobile

EXPLAIN SELECT NAME,mobile FROM user_contacts  WHERE DATE_FORMAT(create_date,'%Y-%m-%d')='2017-02-16';

explain分析的结果显示 type=ALL : 进行了全表扫描,需要进行优化,为create_date字段添加索引.

ALTER TABLE user_contacts ADD INDEX idx_cd(create_date);

EXPLAIN SELECT NAME,mobile FROM user_contacts  WHERE DATE_FORMAT(create_date,'%Y-%m-%d')='2017-02-16';

  • 添加索引后,发现并没有使用到索引 key=null

  • 分析原因: create_date字段是datetime类型 ,转换为日期再匹配,需要查询出所有行进行过滤, 所以导致索引失效.

优化: 

改为使用 between ... and ... ,使索引生效

EXPLAIN SELECT NAME,mobile FROM user_contacts  WHERE create_date BETWEEN '2017-02-16 00:00:00' AND '2017-02-16 23:59:59';

type=range : 使用了索引进行范围查询

Extra=Using index condition; Using MRR :Using index condition 表示使用了部分索引, MRR表示InnoDB存储引擎 通过把「随机磁盘读」,转化为「顺序磁盘读」,从而提高了索引查询的性能.

需求四

 获取用户通讯录表第10万条数据开始后的100条数据.

EXPLAIN SELECT * FROM user_contacts uc LIMIT 100000,100;

-- 查询记录量越来越大,所花费的时间也会越来越多
EXPLAIN SELECT * FROM user_contacts uc LIMIT 1000000,1000;

EXPLAIN SELECT * FROM user_contacts uc LIMIT 2000000,10000;

EXPLAIN SELECT * FROM user_contacts uc LIMIT 3000000,100000;

LIMIT 子句可以被用于指定 SELECT 语句返回的记录数。需注意以下几点:

  • 第一个参数指定第一个返回记录行的偏移量,注意从0开始()

  • 第二个参数指定返回记录行的最大数目

  • 如果只给定一个参数:它表示返回最大的记录行数目

  • 初始记录行的偏移量是 0(而不是 1)

优化1: 通过索引进行分页

直接进行limit操作 会产生全表扫描,速度很慢. Limit限制的是从结果集的M位置处取出N条输出,其余抛弃.

假设ID是连续递增的,我们根据查询的页数和查询的记录数可以算出查询的id的范围,然后配合 limit使用

EXPLAIN SELECT * FROM user_contacts WHERE id  >= 100001 LIMIT 100;

  • type类型提升到了 range级别

优化2: 使用子查询优化 

 

-- 首先定位偏移位置的id
SELECT id FROM user_contacts LIMIT 100000,1;

-- 根据获取到的id值向后查询.
EXPLAIN SELECT * FROM user_contacts WHERE id >=
(SELECT id FROM user_contacts LIMIT 100000,1) LIMIT 100;

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

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

相关文章

2016年新华三杯复赛实验试题

2016年新华三杯复赛实验试题 拓扑图 配置需求 考生根据以下配置需求在 HCL 中的设备上进行相关配置。 以太网接口配置 将 S1、S2 的以太网接口 G1/0/1 至 G1/0/16 的模式用命令 combo enable copper 激活为电口。 虚拟局域网 为了减少广播&#xff0c;需要规划并配置 VLA…

Zabbix监控系统:基础配置及部署代理服务器

目录 前言 一、自定义监控内容 1、在客户端创建自定义key 2、在服务端验证新建的监控项 3、在web界面创建自定义监控项模版 3.1 创建模版 3.2 创建应用集&#xff08;用于管理监控项&#xff09; 3.3 创建监控项 3.4 创建触发器 3.5 创建图形 3.6 将主机与模板关联…

利用selenium发挥vip残存的价值

历史版本谷歌浏览器驱动下载地址 https://chromedriver.storage.googleapis.com/index.html 找到与你电脑当前谷歌浏览器版本一致的驱动然后下载下来(大版本一致即可)。我本地版本是 99.0.04844.51 我这里把 chromedriver 放到 /usr/local/bin 下面了。 启动测试窗口 这里需要…

【软件测试】认识测试|测试岗位|软件测试和开发的区别|优秀的测试人员需要具备的素质

一、什么是测试 测试在⽣活中处处可⻅ 1.生活中的测试场景 案例⼀&#xff1a;对某款购物软件进⾏测试 *启动测试&#xff1a;点击软件图标&#xff0c;测试软件是否可以正常打开 搜索测试&#xff1a;点击输入框&#xff0c;输入关键词&#xff0c;点击搜索 商品测试&#…

【Linux】IO多路转接技术Epoll的使用

【Linux】IO多路转接技术Epoll的使用 文章目录 【Linux】IO多路转接技术Epoll的使用前言正文接口介绍工作原理LT模式与ET模式边缘触发&#xff08;ET&#xff09;水平触发&#xff08;LT&#xff09; 理解ET模式和非阻塞文件描述符ET模式epoll实现TCP服务器简单地封装epoll系统…

python创建线程和结束线程

&#x1f47d;发现宝藏 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。【点击进入巨牛的人工智能学习网站】。 python创建线程和结束线程 在 Python 中&#xff0c;线程是一种轻量级的执行单元&#xff…

【C++学习】STL之空间配置器之一级空间配置器

文章目录 &#x1f4ca;什么是空间配置器✈STL 提供六大组件的了解&#x1f440;为什么需要空间配置器&#x1f44d;SGI-STL空间配置器实现原理&#x1f302;一级空间配置器的实现 &#x1f4ca;什么是空间配置器 空间配置器&#xff0c;顾名思义就是为各个容器高效的管理空间…

“五之链”第十六期沙龙活动在呆马科技成功举办

2024年4月19日&#xff0c;由临沂呆码区块链网络科技有限公司&#xff08;呆马科技&#xff09;承办的第十六期“五之链”物流主题沙龙活动成功举办。此次活动邀请了政府相关部门、知名科研院所、物流企业等20余家单位参与&#xff0c;共同探讨物流数据要素流通与智能应用的发展…

C语言----链表

大家好&#xff0c;今天我们来看看C语言中的一个重要知识&#xff0c;链表。当然大家可以先从名字中看出来。就是一些表格用链子连接。那么大家是否想到了我们以前学的数组&#xff0c;因为数组也是相连的呀。是吧。但是链表与数组还是有区别的&#xff0c;那么链表是什么有什么…

uniApp项目总结

前言 大半年的时间&#xff0c;项目从秋天到春天&#xff0c;从管理后台到APP再到数据大屏&#xff0c;技术栈从vue3到uniApp再到nuxt3&#xff0c;需求不停的改&#xff0c;注释掉代码都快到项目总体的三分之一。 一&#xff0c;项目技术栈分析 1.1 项目框架 当前&#xf…

树与二叉树的学习笔记

树与二叉树 在之前的学习中&#xff0c;我们一直学习的是一个线性表&#xff0c;数组和链表这两种都是一对一的线性表&#xff0c;而在生活中的更多情况我们要考虑一对多的情况&#xff0c;这时候就引申出了我的新的数据结构那就是树&#xff0c;而树经过一些规矩的指定也就成为…

秒懂图神经网络(GNN)

​ 图神经网络&#xff08;GNN&#xff09;是一种深度学习模型&#xff0c;专门为处理图结构数据而设计。在现实世界中&#xff0c;许多数据都可以通过图来表示&#xff0c;比如社交网络中人与人之间的联系、分子结构中的原子连接等。图由顶点&#xff08;或称为节点&#xff0…

LLM使用方法介绍,持续更新

LLM使用方法介绍&#xff0c;持续更新 1. LLM本地搭建与运行 1. Ollama的安装 网址&#xff1a;https://ollama.com/点击Download选择对应的操作系统下载安装软件&#xff0c;软件默认安装在C盘无法选择路径&#xff1b; 安装完成后&#xff0c;WinR进入终端执行&#xff1a…

推荐一个在线stable-diffusion-webui,通过文字生成动画视频的网站-Ai白日梦

推荐一个可以通过文字生成动画视频的网站&#xff0c;目前网站处于公测中&#xff0c;应该是免费的。 点击新建作品 使用kimi或者gpt生成一个故事脚本 输入故事正文 新建作品&#xff0c;选择风格 我这里显示了六个风格&#xff0c;可以根据自己需要选一个 选择配音&…

54、图论-实现Trie前缀树

思路&#xff1a; 主要是构建一个trie前缀树结构。如果构建呢&#xff1f;看题意&#xff0c;应该当前节点对象下有几个属性&#xff1a; 1、next节点数组 2、是否为结尾 3、当前值 代码如下&#xff1a; class Trie {class Node {boolean end;Node[] nexts;public Node(…

Java——三层架构

在我们进行程序设计以及程序开发时&#xff0c;尽可能让每一个接口、类、方法的职责更单一些&#xff08;单一职责原则&#xff09;。 单一职责原则&#xff1a;一个类或一个方法&#xff0c;就只做一件事情&#xff0c;只管一块功能。 这样就可以让类、接口、方法的复杂度更低…

centos7上搭建mongodb数据库

1.添加MongoDB的YUM仓库&#xff1a; 打开终端&#xff0c;执行以下命令来添加MongoDB的YUM仓库&#xff1a; sudo vi /etc/yum.repos.d/mongodb-org-4.4.repo 在打开的文件中&#xff0c;输入以下内容&#xff1a; [mongodb-org-4.4] nameMongoDB Repository baseurlh…

黑马程序员Docker快速入门到项目部署笔记

视频来源&#xff1a; 01.Docker课程介绍_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1HP4118797?p1 Docker官网&#xff1a; docker build | Docker Docshttps://docs.docker.com/reference/cli/docker/image/build/ 一、Docker的安装和配置 1.卸载旧版Docker…

利用STM32的定时器和中断实现精准时间控制

⬇帮大家整理了单片机的资料 包括stm32的项目合集【源码开发文档】 点击下方蓝字即可领取&#xff0c;感谢支持&#xff01;⬇ 点击领取更多嵌入式详细资料 问题讨论&#xff0c;stm32的资料领取可以私信&#xff01; 在嵌入式系统开发中&#xff0c;精确的时间控制是许多应用的…

软考 系统架构设计师系列知识点之大数据设计理论与实践(13)

接前一篇文章&#xff1a;软考 系统架构设计师系列知识点之大数据设计理论与实践&#xff08;12&#xff09; 所属章节&#xff1a; 第19章. 大数据架构设计理论与实践 第4节 Kappa架构 19.4.2 Kappa架构介绍 Kappa架构由Jay Kreps提出&#xff08;Lambda由Storm之父Nayhan M…