【MySQL】索引优化与关联查询优化

news2025/1/19 14:11:05

数据库调优的几个维度:

  • 索引失效,没有充分用到索引——索引建立
  • 关联查询太多JOIN——SQL优化
  • 服务器调优以及各个参数设置——调整my.cnf
  • 数据过多——分库分表

SQL查询优化的几种方式:

  • 物理查询优化:通过索引以及表连接方式进行优化
  • 逻辑查询优化:通过SQL等价变换提升查询效率

一、索引失效案例

1.1、尽量全值匹配

EXPLAIN SELECT SQL_NO_CACHE * FROM student WHERE age=30 AND classId=4 AND NAME='abcd'

CREATE INDEX idx_age ON student(age);                 //执行时间0.149s
CREATE INDEX idx_age ON student(age, classId);        //执行时间0.001s
CREATE INDEX idx_age ON student(age, classId, NAME);  //执行时间0.002s

使用了越多的属性来建立索引,会加快SQL查询的效率,能加速每一个属性的查询

1.2、最佳左前缀法则

CREATE INDEX idx_age ON student(age, classId, NAME);

SELECT  SQL_NO_CACHE * FROM student
WHERE student.age=30 AND student.classId=2 AND NAME='abcd';

在过滤条件(WHERE)中使用了索引的情况下,要按照索引建立时的顺序从左往右筛选,如果中间跳过了某个字段,比如跳过了student.classId,则NAME字段将无法被用来查询

1.3、主键插入顺序

  对于一个使用InnoDB存储引擎的数据库来说,其记录是按照主键值从小到大排序的。如果我们插入的数据是依次递增的,每插满一个数据页就换到下一个数据页继续插。但是插入的数据忽大忽小时,会带来更多得页面分裂以及记录移位。这也就导致了性能损耗。
  所以,可以通过设置主键具有AUTO_INCREMENT,让存储引擎自己为记录生成递增的主键,避免用户手动插入。

1.4、计算、函数、类型转换(自动或者手动)导致索引失效

MySQL中的 类型的值会先作用于函数、计算或者类型转换,再作用于整体的操作

EXPLAIN SELECT SQL_NO_CACHE * FROM student WHERE LEFT(student.name, 3)='abc';
//这条语句MySQL会将name字段的值一个个取出来进行函数操作后再与abc进行比较,所以用不上索引
EXPLAIN SELECT SQL_NO_CACHE * FROM student WHERE student.name LIKE 'abc%';
//而这条语句可以用上索引

1.5、范围条件右边的列索引失效

CREATE INDEX idx_age_classId_name ON student(age, classId, NAME);

EXPLAIN SELECT SQL_NO_CACHE * FROM student 
WHERE student.age=10 AND student.classId>20 AND student.NAME='abc';

  如果对索引的过滤条件中限制了一定范围,那么使用B+数来查询后,索引中剩下字段也就没有意义来。这里由于classId在索引的中间位置,所以在它之后的NAME字段索引失效。
  解决失效的方法为重新设置索引

CREATE INDEX idx_age_name_classId ON student(age, NAME, classId);

1.6 不等号索引失效

  使用!=或者<>导致索引失效,原理同上

1.7、is not null 无法使用索引

  is null可以使用索引,is not null无法使用索引,情况类似于等于号可以使用索引,不等号不能使用索引
  解决这类索引失效问题的方法为:将字段设置为NOT NULL约束,可以设置0为INT类型字段的初始值,空字符串为字符串类型的初始值。

1.8、like以通配符%开头索引失效

EXPLAIN SELECT SQL_NO_CACHE * FROM student WHERE NAME LIKE '%ab'

  开头不确定,所以无法在B+树中搜索

1.9、OR前后存在非索引的列,索引失效

CREATE INDEX student ON student(age)

EXPLAIN SELECT SQL_NO_CACHE * FROM student 
WHERE age=10 OR classId=1

  虽然age可以使用索引,但是classId仍然需要全表扫描,所以整个语句仍然是全表扫描。

1.10、数据库和表的字符集使用不统一

  统一字符集可以避免由于字符集转换产生的乱码,不同字符集进行比较前会进行类型转换导致索引失效。

二、关联查询优化

2.1、左外连接

  在没有索引的情况下进行查询

EXPLAIN SELECT SQL_NO_CACHE * FROM `type` LEFT JOIN book ON type.card=book.card;

  这种情况相当于把type.card值与book.card值一个一个进行比较。
  对被驱动表book.card添加索引后

CREATE INDEX Y ON book(card);
EXPLAIN SELECT SQL_NO_CACHE * FROM `type` LEFT JOIN book ON type.card = book.card;

  这里相当于驱动表type是一个一个的取,而被驱动表book则是在B+树上进行快速查找

2.2、内连接

  在内连接中小表驱动大表,优化器会对两个表进行计算,将数据量小的表作为驱动表,数据量大的表作为被驱动表。

CREATE INDEX X ON book(card);
EXPLAIN SELECT SQL_NO_CACHE * FROM book INNER JOIN `type` ON book.card = `type`.card; 

  在上面这个语句中,虽然book表在等号左边,但是只有book表具有索引,因此,这里的被驱动表仍然是book表

2.3、JOIN语句原理

  JOIN方式连接多个表,本质上就是各个表之间数据的循环匹配

  • 简单嵌套循环连接(Simple Nested-Loop Join)
      这种方式的效率最低,其算法为将驱动表A中的每一条记录都与被驱动表B进行匹配。
    在这里插入图片描述
  • 索引嵌套循环连接(Index Nested-Loop Join)
      索引嵌套循环连接的优化思路主要是使用索引来替换全表查找来进行优化,从而减小内表的查询次数。
    在这里插入图片描述
  • 块嵌套循环连接(Block Nested-Loop Join)
      为了减少被驱动表的IO次数,出现了块嵌套循环连接的方式,引入了Join buffer 缓冲区,将驱动表的部分数据缓冲到buffer中,然后全表扫描被驱动表进行匹配,将简单嵌套循环中的多次合并为一次,降低了被驱动表的访问频率。

在这里插入图片描述

  • Hash Join
      Hash Join是做大数据集连接时的常用方式,优化器使用较小的表利用Join Key在内存中建立散列表,扫描较大的表并探测散列表进行搜索。

总结

  • 对于JOIN的内部实现来说,整体效率比较INLJ > BNLJ > SNLJ
  • 永远用小结果集驱动大结果集(结果集大小的判断为表行数*每行大小
  • 在INLJ中,为被驱动表匹配的条件增加索引,能够减少内层表的循环匹配次数
  • 在BNLJ中,增大Join buffer size,可以在内存中存下更多得行数,减少内层表的扫描次数
  • 在BNLJ中,减少不必要的字段查询。

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

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

相关文章

Day30-Linux基础阶段总复习

Day30-Linux基础阶段总复习 1. 运维人员的三个核心职责&#xff08;了解&#xff09;2. 企业网站和应用的可用性的衡量标准&#xff08;重点&#xff09;2.1 高并发企业业务写入流程图2.2 中小型企业案例 3. Linux系统诞生发展过程中的关键代表人物4. 企业场景如何针对不同的业…

Springboot配置MySQL数据库

Springboot配置MySQL数据库 一、创建springboot项目&#xff0c;并添加如下依赖 <dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId><scope>runtime</scope> </dependency>二、在applica…

Django框架——路由

上篇文章我们学习了Django框架——请求与响应&#xff0c;这篇文章我们学习Django框架——路由。本次学习过程中使用的项目目录如下图所示&#xff1a; 大家放心&#xff0c;这个是新建的Django项目&#xff0c;还没编写任何代码&#xff0c;这里展示目录是为了大家更好地理解本…

力扣大厂热门面试算法题 - 矩阵

解数独&#xff0c;单词搜索&#xff0c;被围绕的区域。每题做详细思路梳理&#xff0c;配套Python&Java双语代码&#xff0c; 2024.03.07 可通过leetcode所有测试用例。 目录 37. 解数独 解题思路 完整代码 Python Java 79. 单词搜索 解题思路 完整代码 Python…

金融行业数据安全面临的问题及解决办法

金融行业包括商业银行业务、证券业务、保险业务、基金业务、信托业务等&#xff0c;因此数据类型多种多样&#xff0c;并且数据涉及主体众多&#xff0c;应用场景上较为多样复杂&#xff0c;在数据交换上存在安全、合规、可控、可靠、高效等需求。首先&#xff0c;我们来看一下…

c++初阶------类和对象(六大默认构造函数的揭破)

作者前言 &#x1f382; ✨✨✨✨✨✨&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f382; ​&#x1f382; 作者介绍&#xff1a; &#x1f382;&#x1f382; &#x1f382; &#x1f389;&#x1f389;&#x1f389…

部署YOLOv8模型的实用常见场景

可以的话&#xff0c;GitHub上点个小心心&#xff0c;翻不了墙的xdm&#xff0c;csdn也可以点个赞&#xff0c;谢谢啦 车流量检测&#xff08;开源代码github&#xff09;&#xff1a; test3 meiqisheng/YOLOv8-DeepSORT-Object-Tracking (github.com) 车牌检测&#xff0…

代码随想录算法训练营第11天

20. 有效的括号 方法&#xff1a; 1. 如果 !st.empty() return false2.如果st.top() ! s[i] return false3. 如果 st.empty() return false注意&#xff1a; 以下这种写法 不满足 题目要求的第二点&#xff0c;不能以正确的顺序闭合 if(s[i] st.top()){return true;s…

openssl调试记录

openssl不能直接解密16进制密文&#xff0c;需要把密文转化成base64格式才能解密 调试记录如下&#xff1a;

【必读】产品经理必须要熟练掌握的五类产品管理框架

产品管理从其传统根源已经走过了很长一段路&#xff0c;不断发展以适应现代企业的步伐和需求。随着产品变得更加复杂&#xff0c;用户的需求更加细致&#xff0c;用于指导这些产品的框架需要升级。请阅读本文&#xff0c;深入了解从字面上看改变了产品管理游戏规则的结构。 01.…

越南、泰国发稿案例分析:CloudNEO专家级海外新闻传播矩阵

在东南亚地区&#xff0c;越南和泰国作为经济增长迅速、市场潜力巨大的国家&#xff0c;吸引着越来越多的国际企业进驻和投资。在这个充满机遇和挑战的市场中&#xff0c;有效的新闻传播成为企业赢得市场份额和建立品牌形象的关键一环。CloudNEO作为专业的海外新闻传播服务提供…

事务 失效的八种情况

在某些业务场景下&#xff0c;如果一个请求中&#xff0c;需要同时写入多张表的数据。为了保证操作的原子性&#xff08;要么同时成功&#xff0c;要么同时失败&#xff09;&#xff0c;避免数据不一致的情况&#xff0c;我们一般都会用到 spring 事务。 确实&#xff0c;sprin…

docker-compose Install ONLYOFFICE

ONLYOFFICE 前言 ONLYOFFICE 是一款全面的协作办公软件套件,集成了文档处理、电子表格和演示文稿等功能,为团队提供了无缝协作的工作环境。其功能强大,操作简便,是各种规模和类型的团队的首选工具。 功能介绍 多人协作:ONLYOFFICE 提供实时协作功能,让团队成员可以同时…

【设计模式 04】建造者模式

如果要构建的对象很复杂&#xff0c;那么可以将整个构建过程拆分成多个步骤&#xff0c;并为每一个步骤定义一个抽象的接口。并添加一个指导者用来控制构建产品的顺序和步骤。 Java实现&#xff1a; // 产品类 class Product {private String part1;private String part2;pub…

vue3+ts项目创建 使用npm create vue@latest

npm create vuelatest相关创建代码&#xff1a;

android基础学习

从上面的描述就可以知道&#xff0c;每一个Activity组件都有一个对应的ViewRoot对象、View对象以及WindowManager.LayoutParams对象。这三个对象的对应关系是由WindowManagerImpl类来维护的。具体来说&#xff0c;就是由WindowManagerImpl类的成员变量mRoots、mViews和mParams所…

onnxruntime模型部署(二)C++部署手写数字识别

导出onnx模型 模型链接&#xff1a; 夸克网盘链接 百度网盘链接&#xff0c;提取码&#xff1a;8fkb 环境配置 OpenCV配置 自行百度 onnxruntime C版配置 有两种方法&#xff0c;一种是下载源码自己编译&#xff0c;还有一种是使用预编译好的文件。众说周知&#xff0c;…

Vue深度教程

一、Vue简介 1.简介 2.快速上手 二、基础 1.创建一个Vue应用 2.模板语法 3.响应式基础 4.计算属性 5.Class与 Style绑定 6.条件渲染 7.列表渲染 8.事件处理 9.表单输入绑定 10.生命周期钩子 11.侦听器 12.模板引用 13.组件基础 三、深入组件 1.组件注册 2.Props 3.组件事件 …

xinput1_3.dll丢失都有什么办法可以有效的解决、xinput1_3.dll导致游戏不能启动怎么办?

使用电脑的过程中是不是会遇到关于某个dll文件丢失的提示&#xff0c;今天想和大家聊的是xinput1_3.dll文件&#xff0c;如果电脑提示xinput1_3.dll丢失有什么办法可以有效的解决&#xff0c;解决办法都有哪些&#xff0c;如果xinput1_3.dll丢失会对电脑有什么影响。&#xff0…

详解高质量增长的关键动力:ABM、数据、AI与业财融合

企业要穿越周期&#xff0c;不能仅靠节衣缩食&#xff0c;增长与盈利仍是必须。当盲目做大规模无法带来可持续发展&#xff0c;高质量增长便成为必须。在降本增效之上&#xff0c;企业需要变革增长模式。 在纷享销客的《领创者》开年直播上&#xff0c;纷享销客联合创始人、经…