10 索引优化与查询优化

news2024/11/26 18:31:05

文章目录

  • 索引失效案例
  • 关联查询优化
      • 对于左外连接
      • 对于内连接
      • JOIN语句原理
        • 简单嵌套循环连接SNLJ
        • 索引嵌套循环连接INLJ
        • 块嵌套循环连接BNLJ
        • Hash Join
  • 子查询优化
  • 排序优化
      • filesort算法:双路排序和单路排序
  • 分组优化
  • 分页优化
  • 优先考虑覆盖索引
  • 索引下推ICP
      • 使用条件
  • 其他查询优化策略

MySQL中提高性能的最有效的方式是对数据表设计合理的索引,使用索引可以快速地定位表中的某条记录,从而提高数据库查询的速度,提高数据库的性能。如果查询时没有使用索引,查询语句就会扫描表中的所有记录,在数据量大的情况下,这样查询的速度就会很慢。

大多数情况下默认采用B+树来构建索引。

索引是否采用是由基于cost开销的优化器决定的,另外,是否使用索引跟数据库版本、数据量和数据选择度都有关系。

索引失效案例

  1. 全值匹配我最爱

  2. 最佳左前缀法则
    MySQL中一个索引可以包括16个字段,它检索数据时遵守最佳左前缀匹配原则,即从联合索引的最左边字段开始匹配
    用户在创建索引时,对于多列索引,过滤条件要使用索引必须按照索引建立的顺序,依次满足,一旦跳过某个字段,索引后面的字段都失效。如果查询条件中没有使用第一个字段,联合索引不会被使用

  3. 主键插入顺序
    如果插入的主键值忽大忽小,则可能会造成页分裂和记录移位

  4. 计算、函数会导致索引失效

  5. 类型转换(自动或手动)导致索引失效

  6. 范围条件右边的列索引失效

  7. 不等于(≠或<>)索引失效

  8. is null可以使用索引,is not null索引失效

  9. LIKE以通配符%开头索引失效

  10. OR前后存在非索引的列索引失效

  11. 数据库和表的字符集统一使用utf8mb4

关联查询优化

对于左外连接

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

type相当于驱动表,book相当于被驱动表
如果左连接中,只能给一个字段添加索引,就要添加给被驱动表,原因是左连接左边一定都有,关键在于如何从右表搜索行。

对于内连接

由查询优化器来决定谁作为驱动表,谁作为被驱动表出现
如果表的连接条件只能有一个字段有索引,则有索引的字段所在的表会作为被驱动表
在两个表都存在索引的情况下,会选择小表作为驱动表

JOIN语句原理

简单嵌套循环连接SNLJ
索引嵌套循环连接INLJ

优化思路是减少内层表数据的匹配次数,所以要求是被驱动表上必须有索引
在这里插入图片描述

块嵌套循环连接BNLJ

如果被驱动表中没有索引,那么被扫描的次数太多了,IO次数也很多。
优化思路是减少被驱动表的IO次数,一块一块地获取驱动表的数据。引入join buffer缓冲区,将驱动表相关的部分数据列缓冲到join buffer中,然后全盘扫描被驱动表,被驱动表中的每一条记录一次性跟buffer中的所有驱动表记录进行匹配,降低了被驱动表的访问频率

在这里插入图片描述

Hash Join

是做大数据集连接时常用方式,优化器将相对较小的表在内存中建立散列值,然后扫描较大的表并探测散列值,找出与Hash表匹配的行

  1. 这种方式适用于较小的表完全可以放入内存中的情况,这样总成本就是访问两个表的成本之和

  2. 若表很大不能完全放入内存,这是优化器会将其分割成若干个不同的分区,不能放入内存的部分就把该分区写入磁盘的临时段

  3. 能够很好的工作于没有索引的大表和并行查询的环境中,并提供很好的性能。

  4. 只能应用于等值连接,这是由hash的特点决定的

子查询优化

概念:一个SELECT查询的结果作为另一个SELECT语句的条件,使用子查询可以实现查询语句的嵌套查询

子查询的执行效率不高的原因:1.MySQL需要为内层查询语句的查询结果建立一个临时表,然后外层查询语句从临时表中查询记录,查询完毕后再撤销这些临时表。这样会消耗过多的CPU和IO资源,产生大量的慢查询
2.子查询结果集存储的临时表,不会存在索引,所以查询性能会收到影响
3.对于返回结果较大的子查询,其对查询性能的影响也就越大

使用连接查询代替子查询

SELECT * FROM student stu 
WHERE stu.stuno IN (
  SELECT monitor FROM class c
  WHERE monitor IS NOT NULL
);

SELECT stu.* FROM student stu 
JOIN class c ON stu.stuno=c.monitor 
WHERE c.monitor IS NOT NULL
SELECT stu.* FROM student stu 
WHERE stu.stuno NOT IN (
  SELECT monitor FROM class c
  WHERE monitor IS NOT NULL
);

SELECT stu.* FROM student stu 
LEFT OUTER JOIN class c ON stu.stuno=c.monitor 
WHERE c.monitor IS NOT NULL

排序优化

排序使用索引的原因:索引可以保证数据的有序性,效率更高,filesort排序一般在内存中进行,占用CPU较多,如果待排序结果较大,会产生临时文件IO到磁盘进行排序的情况,效率较低。

  1. 增加LIMIT过滤条件索引有效

  2. 保证字段顺序索引有效

  3. 升序降序一致或顺序全不一致索引有效

filesort算法:双路排序和单路排序

双路排序:扫描磁盘读取order列,在buffer中进行排序,再按照排序列表从磁盘中读取其他字段

单路排序:从磁盘读取所有列,在buffer中按照order进行排序,之后输出。它的效率更快一点,避免了第二次读取数据,并且把随机IO变成了顺序IO,但是他会使用更多的空间

分组优化

类似于排序优化

分页优化

  1. 在索引上完成排序分页操作,然后根据主键关联回原表查询所需要的其他列内容

  2. 将LIMIT查询转换为某个位置的查询

优先考虑覆盖索引

概念:建索引的字段覆盖了查询条件所涉及的字段。索引的叶子节点存储了所需要的数据,通过读取索引就可以得到所需数据无需回表

好处:避免进行回表;可以把随机IO变成顺序IO

弊端:索引字段的维护是有代价的

索引下推ICP

是MySQL5.6的新特性,是一种在存储引擎层使用索引过滤数据的优化方式。ICP可以减少回表的次数以及MySQL服务器访问存储引擎的次数

启用ICP后,如果WHERE条件可以使用索引中的列进行筛选,则MySQL服务器会把这部分条件使用索引条目进行筛选数据,最后才回表读取数据

使用条件

  1. 只能用于二级索引

  2. EXPLAIN显示的执行计划中type值为range、ref、eq_ref和ref_or_null

  3. 只有在索引列中的WHERE条件字段才可以用ICP筛选

  4. ICP可以用于MyISAM和InnoDB存储引擎

  5. 当SQL使用覆盖索引时,不支持ICP优化方法

  6. 相关子查询条件不能使用ICP

其他查询优化策略

  1. EXISTS和IN的区分
    SELECT * FROM A WHERE cc IN (SELECT cc FROM B),哪个表小就用哪个表来驱动,A表小就用EXISTS,B表小就用IN

  2. COUNT()、COUNT(1)和COUNT(具体字段)的效率
    · COUNT(
    )和COUNT(1)都是统计所有结果,本质上没有区别,如果有WHERE子句,则是对所有符合条件的数据行进行统计,如果没有WHERE子句,则是对数据表的数据行数进行统计
    · 如果是MyISAM,统计数据表的行数只需要O(1)的复杂度,因为每个数据表都有一个meta信息存储了row_count值,其一致性由表级锁保证;如果是InnoDB,因为其支持事务,采用行级锁和MVCC机制,无法维护一个row_count变量,因此需要扫描全表,是O(n)的复杂度
    · 在InnoDB中,如果采用COUNT(具体字段)来统计具体数据行数,尽量采用二级索引。因为聚簇索引包含的信息多。对于COUNT(*)、COUNT(1),不需要查找具体的行,只是统计行数,系统会自动采用空间更小的二级索引来统计

  3. SELECT(*)
    尽量不要使用**,因为需要通过查询数据字典转换为所有列名,这会耗费资源和时间;且无法使用覆盖索引

  4. LIMIT 1对优化的影响
    针对全盘扫描,如果确定结果集只有一条,加上LIMIT 1,扫描到一条结果就不会再扫描,这样会加快查询速度。如果对字段已经建立了唯一索引,则不会进行全盘扫描,不需要加LIMIE 1

  5. 多使用COMMIT
    程序性能会得到提高,需求会因为COMMIT所释放的资源而减少。COMMIT所释放的资源有:回滚段上用于恢复数据的信息,被程序语句获得的锁,redo / undo log buffer中的空间,管理上述3中资源的内部花费

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

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

相关文章

[移动通讯]【Carrier Aggregation-13】【Carrier Aggregation】

前言&#xff1a; 前面分享过不同note CA 技术文档 这里主要参考 4G|ShareTechnote 《Carrier Aggregation》 CA SCell 添加的小区的流程&#xff1a; SCell addition and removal&#xff1a; 1 The carrier aggregation additional SCells cannot be activated immediately…

Firefox 119 正式发布

Firefox 119 已正式发布。新版本除了修复 Bug 之外&#xff0c;还增强了 Firefox View 功能、支持在 PDF 文档中插入图片&#xff0c;以及引入 Encrypted Client Hello (ECH) 以增强隐私保护等。 主要变化 改进 Firefox View&#xff1a;用户可以在该页面查看所有窗口打开的标…

uniapp 微信小程序 uni-file-picker上传图片报错 chooseAndUploadFile

这个问题真的很搞&#xff0c; 原因是微信开发者工具更新了&#xff0c;导致图片上传问题。 解决方法&#xff1a; 将微信开发者工具的基础库改为2.33.0一下即可。 在微信开发者工具详情 - 本地设置中&#xff08;记得点击‘推送’按钮&#xff09;&#xff1a;

20.8 OpenSSL 套接字SSL传输文件

有了上面的基础那么传输文件的实现就变得简单了&#xff0c;在传输时通常我们需要打开文件&#xff0c;并每次读入1024个字节的数据包&#xff0c;通过SSL加密传输即可&#xff0c;此处的文件传输功能在原生套接字章节中也进行过详细讲解&#xff0c;此处我们还是使用原来的密钥…

Spark 基础知识点

Spark 基础 本文来自 B站 黑马程序员 - Spark教程 &#xff1a;原地址 什么是Spark 什么是Spark 1.1 定义&#xff1a;Apache Spark是用于大规模数据&#xff08;large-scala data&#xff09;处理的统一&#xff08;unified&#xff09;分析引擎 Spark最早源于一篇论文 Re…

Linux 学习(CentOS 7)

CentOS 7 学习 Linux系统内核作者: Linux内核版本 内核(kernel)是系统的心脏&#xff0c;是运行程序和管理像磁盘和打印机等硬件设备的核心程序&#xff0c;它提供了一个在裸设备与应用程序间的抽象层。 Linux内核版本又分为稳定版和开发版&#xff0c;两种版本是相互关联&am…

深度优先遍历与连通分量

深度优先遍历(Depth First Search)的主要思想是首先以一个未被访问过的顶点作为起始顶点&#xff0c;沿当前顶点的边走到未访问过的顶点。当没有未访问过的顶点时&#xff0c;则回到上一个顶点&#xff0c;继续试探别的顶点&#xff0c;直至所有的顶点都被访问过。 下图示例的…

设置Linux时间格式

一、事因 不知道什么时候我在输入ls -l 命令时候的显示变成了。 -rw-r--r-- 1 bossftp ftp 6796376499 915 05:31 rac_full_20230915.gz -rw-r--r-- 1 bossftp ftp 6804104515 104 05:25 rac_full_20231024.gz -rw-r--r-- 1 bossftp ftp 6804365525 105 05:29 rac_full_202…

技术分享 | Selenium多浏览器处理

实战演示 Python 版本 #导入依赖 import os from selenium import webdriverdef test_browser():#使用os模块的getenv方法来获取声明环境变量browserbrowser os.getenv("browser").lower()#判断browser的值if browser "headless":driver webdriver.Ph…

python web框架 flask基础入门教程

python web框架 flask基础入门教程 今天我们写一个flask基础入门教程&#xff0c;当然也会覆盖很多重要的知识点&#xff0c;在这篇博客中&#xff0c;我们主要会讲解如下内容&#xff1a; 1、通过flask框架向web传输和接收参数 2、实现静态图片插入和图书上传 3、实现搭建…

函数调用指令, 返回机制分析(x86_64)

预备 #include <stdio.h>int addDetail(int a, int b) {return a b; }int add(int a, int b) {int c;c addDetail(a, b);return c; }int main(int argc, char *argv[]) {int sum;sum add(3, 5);printf("sum %d\n", sum);return 0; }汇编 main add addDeta…

前端食堂技术周刊第 103 期:10 月登陆 Web 平台的新功能、TS 5.3 RC、React 2023 状态、高并发的哲学原理、Web 资源加载优先级

美味值&#xff1a;&#x1f31f;&#x1f31f;&#x1f31f;&#x1f31f;&#x1f31f; 口味&#xff1a;夏梦玫珑 食堂技术周刊仓库地址&#xff1a;https://github.com/Geekhyt/weekly 大家好&#xff0c;我是童欧巴。欢迎来到前端食堂技术周刊&#xff0c;我们先来看下…

数据集划分:手动划分文件夹中的图片数据集为训练集、验证集和测试集

1.需求 手动划分文件夹中的图片数据集为训练集、验证集和测试集&#xff0c;即进行文件夹中的数据集&#xff08;都是图片&#xff09;进行划分。 2.步骤 使用文件处理库&#xff08;如os&#xff09;遍历读取文件夹中的图片文件。将读取到的图片文件路径存储到列表中。打乱…

8、Python模块和包:导入模块、创建自己的模块和包

文章目录 Python模块和包:导入模块、创建自己的模块和包导入模块创建自己的模块创建包使用相对导入结论Python模块和包:导入模块、创建自己的模块和包 Python是一种功能强大的编程语言,它的模块和包系统是其强大功能的基石之一。在Python中,模块是包含Python定义和声明的文…

【MySQL事务篇】多版本并发控制(MVCC)

多版本并发控制(MVCC) 文章目录 多版本并发控制(MVCC)1. 概述2. 快照读与当前读2.1 快照读2.2 当前读 3. MVCC实现原理之ReadView3.1 ReadView概述3.2 设计思路3.3 ReadView的规则3.4 MVCC整体操作流程 4. 举例说明4.1 READ COMMITTED隔离级别下4.2 REPEATABLE READ隔离级别下 …

viewBinding与反射结合的实用实践

首先&#xff0c;官方教程指个路&#xff1a;视图绑定 本文阅读认真阅读大约需要5-20分钟 也可直接跳到文末3.0看最终方案 目录 1 关于ViewBinding第一点&#xff0c;命名符合一定的规则第二点&#xff0c;继承自ViewBinding 2 正常使用不便之处3 话不多说直接看代码1.04 话不…

数据结构与算法之美学习笔记:16 | 二分查找(下):如何快速定位IP对应的省份地址?

目录 前言二分查找的变形问题变体一&#xff1a;查找第一个值等于给定值的元素变体二&#xff1a;查找最后一个值等于给定值的元素变体三&#xff1a;查找第一个大于等于给定值的元素变体四&#xff1a;查找最后一个小于等于给定值的元素 解答开篇内容小结 前言 本节课程思维导…

vue3+ts 项目遇到的问题和bug

1.router中使用pinia报错 pinia.mjs:1709 Uncaught Error: [&#x1f34d;]: "getActivePinia()" was called but there was no active Pinia. Are you trying to use a store before calling "app.use(pinia)"? See https://pinia.vuejs.org/core-concep…

[科研图像处理]用matlab平替image-j,有点麻烦,但很灵活!

做材料与生物相关方向的同学应该对image-j并不陌生&#xff0c;前几天有个师兄拜托我用image-j分析一些图片&#xff0c;但使用过后发现我由于不了解image-j的工作流程而对结果并不确信&#xff0c;而且image-j的功能无法拓展&#xff0c;对有些图片的处理效果并不好&#xff0…

【网络协议】聊聊HTTPDNS如何工作的

传统 DNS 存在哪些问题&#xff1f; 域名缓存问题 我们知道CND会进行域名解析&#xff0c;但是由于本地会进行缓存对应的域名-ip地址&#xff0c;所以可能出现过期数据的情况。 域名转发问题 出口 NAT 问题 域名更新问题 解析延迟问题 因为在解析DNS的时候&#xff0c;需要进行…