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

索引单表优化案例

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.mfbz.cn/a/566796.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

李沐53_语言模型——自学笔记

语言模型 1.预测文本序列出现的概率 2.应用在做预训练模型 3.生成文本&#xff0c;给定前面几个词&#xff0c;不断生成后续文本 4.判断多个序列中哪个更常见 真实数据集的统计 《时光机器》数据集构建词表&#xff0c; 并打印前10个最常用的&#xff08;频率最高的&…

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

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

Python | Leetcode Python题解之第43题字符串相乘

题目&#xff1a; 题解&#xff1a; class Solution:def multiply(self, num1: str, num2: str) -> str:if num1 "0" or num2 "0":return "0"m, n len(num1), len(num2)ansArr [0] * (m n)for i in range(m - 1, -1, -1):x int(num1[i…

【技术干货】润石红外额温枪方案芯片功能介绍

手持红外额温枪框图中&#xff0c;以电池采用9V为例&#xff0c;先通过一个高压LDO RS3002 把电池电压转为3V&#xff0c;供整个系统使用&#xff0c;包括为 MCU&#xff0c;背光灯&#xff0c;运放 等器件供电&#xff0c;然后再用一个低功耗LDO RS3236 从3V 降为1.5V&#…

Excel如何计算时间差

HOUR(B1-A1)&"小时 "&MINUTE(B1-A1)&"分钟 "&SECOND(B1-A1)&"秒"

10种常用的JS数组循环及其应用场景

文章的更新路线&#xff1a;JavaScript基础知识-Vue2基础知识-Vue3基础知识-TypeScript基础知识-网络基础知识-浏览器基础知识-项目优化知识-项目实战经验-前端温习题&#xff08;HTML基础知识和CSS基础知识已经更新完毕&#xff09; 正文 在JavaScript中&#xff0c;数组是一种…

如何在PostgreSQL中实现基于哈希的分区表以及其优势是什么

文章目录 一、基于哈希的分区表实现二、基于哈希的分区表优势 PostgreSQL是一个功能强大的开源关系型数据库管理系统&#xff0c;它支持多种分区策略&#xff0c;包括基于范围的分区、基于列表的分区以及基于哈希的分区。本文将重点讨论如何在PostgreSQL中实现基于哈希的分区表…

青否数字人直播带货源码有哪些功能?

青否数字人直播源码功能如下&#xff1a; 1、青否数字人克隆源码的克隆效果媲美真人 将真人录制的2-6分钟视频上传至克隆端后台&#xff0c;系统便会自动启动自动克隆。3-5小时后&#xff0c;即可生成一个与本人在形象、表情及动作上1&#xff1a;1的数字人。 2、在声音克隆上&…

Vue 3中的ref和toRefs:响应式状态管理利器

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

[MySQL]运算符

1. 算术运算符 (1). 算术运算符 : , -, *, / 或 DIV, % 或MOD. (2). 例 : (3). 注 : DUAL是伪表.可以看到4/2结果为小数&#xff0c;并不会截断小数部分.(可能与其他语言不同&#xff0c;比如java中&#xff0c;两个操作数如果是整数&#xff0c;则计算得到的也是整数&…

面试经典150题——二叉树展开为链表

​ 1. 题目描述 2. 题目分析与解析 2.1 思路一 因为题目中提到&#xff1a;展开后的单链表应该与二叉树 先序遍历 顺序相同&#xff0c;那么我们是不是就可以先先序遍历&#xff0c;然后按照先序遍历的节点一个一个赋值&#xff1f; 其实最简单的思路就是用一个结构按顺序存…

加速大数据分析:Apache Kylin使用心得与最佳实践详解

Apache Kylin 是一个开源的分布式分析引擎&#xff0c;提供了Hadoop之上的SQL接口和多维分析&#xff08;OLAP&#xff09;能力以支持大规模数据。它擅长处理互联网级别的超大规模数据集&#xff0c;并能够进行亚秒级的查询响应时间。Kylin 的主要使用场景包括大数据分析、交互…

Web前端安全问题分类综合以及XSS、CSRF、SQL注入、DoS/DDoS攻击、会话劫持、点击劫持等详解,增强生产安全意识

前端安全问题是指发生在浏览器、单页面应用、Web页面等前端环境中的各类安全隐患。Web前端作为与用户直接交互的界面&#xff0c;其安全性问题直接关系到用户体验和数据安全。近年来&#xff0c;随着前端技术的快速发展&#xff0c;Web前端安全问题也日益凸显。因此&#xff0c…

Altair:Python数据可视化库的魅力之旅

目录 一、引言 二、Altair概述 三、Altair的核心特性 1.声明式语法 2.丰富的图表类型 3.交互式与响应式 4.无缝集成 四、案例与代码实践 案例一&#xff1a;使用Altair绘制折线图 案例二&#xff1a;使用Altair绘制热力图 五、新手入门指南 1.安装与导入 2.数据准…

Nacos服务注册中心

1.引入依赖 <dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency>2.application.properties中配置 # 应用名称 spring.application.namenacos-aserver…

美国洛杉矶服务器的特点

美国洛杉矶的服务器提供多种优质的托管服务&#xff0c;具有较好的网络连接速度和稳定性。以下是一些洛杉矶服务器的特点和服务&#xff0c;rak小编为您整理发布。 1. **地理位置优势**&#xff1a;位于美国西海岸的洛杉矶机房离中国相对较近&#xff0c;这有助于减少延迟&…

指针专题(4)【qsort函数的概念和使用】

1.前言 上节我们学习了指针的相关内容&#xff0c;本节我们在有指针的基础的条件下学习一下指针的运用&#xff0c;那么废话不多说&#xff0c;我们正式进入今天的学习 2.回调函数 我们既然已经学习了指针的相关基础&#xff0c;那么我们此时就可以用指针来实现回调函数 而回…

如何在在wordpress安装百度统计

前言 看过我的往期文章的都知道&#xff0c;我又建了一个网站&#xff0c;这次是来真的了。于是&#xff0c;最近在查阅资料时发现&#xff0c;有一款免费的软件可以帮我吗分析网站数据。&#xff08;虽然我的破烂网站压根没人访问&#xff0c;但是能装上的都得上&#xff0c;…

python爬虫 - 爬取html中的script数据(爬取 zum.com新闻)

文章目录 1. 分析页面内容数据格式2. 使用re.findall方法&#xff0c;编写爬虫代码3. 使用re.search 方法&#xff0c;编写爬虫代码 1. 分析页面内容数据格式 &#xff08;1&#xff09;打开 https://zum.com/ &#xff08;2&#xff09;按F12&#xff08;或 在网页上右键 --…

免 Administrator 权限安装软件

以欧路词典为例, 从官网下载的安装包 https://www.eudic.net/v4/en/app/download 直接运行会弹出 UAC 提示需要管理员权限. 一个词典而已, 为啥要管理员权限呢? 答案是安装程序默认使用的安装路径是 C:\Program Files\ 这就不难理解了. 对于这种不需要其他额外权限的软件, 可以…
最新文章