4.2.2 MySQL索引原理以及SQL优化

文章目录

  • 4.2.2 MySQL索引原理以及SQL优化
    • 1. 索引与约束
      • 1. 索引是什么
      • 2. 索引的目的
      • 3. 几种索引
      • 4. 约束
        • 1.外键
        • 2. 约束 vs 索引的区别
      • 5. 索引实现
        • 1. 索引存储
        • 2. 页
        • 3. B+树
        • 4. B+树层高问题
        • 5. 自增id
        • 6. 聚集索引
        • 7. 辅助索引
      • 8. innnodb体系结构
        • 1. buffer pool
        • 2. change buffer
      • 9. 最左匹配原则
      • 10. 覆盖索引
      • 11. 索引下推
      • 12. 索引失效
      • 13. 索引原则
    • 2. sql比较慢怎么办
      • 1. 慢查询日志

4.2.2 MySQL索引原理以及SQL优化

1. 索引与约束

1. 索引是什么

  1. 索引是一种有序的数据结构,MySQL 中主要使用 B+ 树(InnoDB 引擎)来组织索引
  2. 它通过加快数据检索速度来提升数据库的查询效率
  3. 可理解为:数据库中的“目录”或“书的页码”
  4. 按照单个或者多个进行排序

2. 索引的目的

提升搜索效率

3. 几种索引

  1. 主键索引
    • 表的唯一标识
    • 不能为空 (NOT NULL) 且唯一 (UNIQUE)
    • 每张表只能有一个主键
    • 创建主键索引时,MySQL自动建立索引(底层通常是B+树)
-- 创建表时指定主键
CREATE TABLE users (id INT PRIMARY KEY,name VARCHAR(50)
);-- 或者先创建表,再加主键
ALTER TABLE users ADD PRIMARY KEY (id);
  1. 唯一索引
    • 保证列值唯一,但允许为空(特殊场景除外)
    • 不作为主键,可以有多个唯一索引
    • 通常用于:手机号、邮箱、身份证号等
-- 创建唯一索引
CREATE TABLE employees (emp_id INT,email VARCHAR(100) UNIQUE,phone VARCHAR(20),PRIMARY KEY (emp_id)
);-- 或者后期添加唯一索引
ALTER TABLE employees ADD UNIQUE (email);
  1. 普通索引
    • 仅加速查询速度
    • 没有唯一性要求,key可以重复
    • 可以为经常用作条件查询(WHERE)的列加普通索引
-- 创建普通索引
CREATE TABLE articles (id INT PRIMARY KEY,title VARCHAR(200),content TEXT
);-- 给 title 添加普通索引
CREATE INDEX idx_title ON articles(title);-- 或者这样
ALTER TABLE articles ADD INDEX (title);
  1. 组合索引
    • 一个索引包含多个列
    • 适合多列联合查询的场景
    • 遵循最左前缀原则(查询时条件必须从索引的最左列开始)
-- 创建组合索引
CREATE TABLE orders (order_id INT PRIMARY KEY,user_id INT,product_id INT,order_date DATE
);-- 给 (user_id, product_id) 建组合索引
CREATE INDEX idx_user_product ON orders(user_id, product_id);-- 查询时如果条件是 user_id,或 user_id + product_id,则可以用到索引
SELECT * FROM orders WHERE user_id = 123;SELECT * FROM orders WHERE user_id = 123 AND product_id = 456;-- 但如果单查 product_id,是用不了这个组合索引的
  1. 全文索引
    • 用于全文搜索
    • 适合大文本内容的搜索
    • 通常用于:文章、博客、产品描述等
-- 1. 创建表
CREATE TABLE blog_posts (id INT PRIMARY KEY AUTO_INCREMENT,title VARCHAR(255),content TEXT,FULLTEXT(title, content)
);-- 2. 插入数据
INSERT INTO blog_posts (title, content) VALUES
('MySQL Tutorial', 'Learn how to use MySQL database.'),
('Fulltext Search', 'Learn about fulltext search in MySQL.');-- 3. 搜索
SELECT * FROM blog_posts
WHERE MATCH(title, content) AGAINST('MySQL');
  1. 主键选择
    innodb 中表是索引组织表,每张表有且仅有一个主键;
    1. 如果显示设置 PRIMARY KEY ,则该设置的 key 为该表的主键;
    2. 如果没有显示设置,则从非空唯一索引中选择;
    3. 只有一个非空唯一索引,则选择该索引为主键;
    4. 有多个非空唯一索引,则选择声明的第一个为主键;
    5. 没有非空唯一索引,则自动生成一个 6 字节的 _rowid 作为主键;

4. 约束

InnoDB 本身提供对这些约束(PRIMARY KEY(主键约束),UNIQUE(唯一约束),NOT NULL(非空约束),FOREIGN KEY(外键约束),CHECK(检查约束))的支持,保证数据的正确性、安全性

1.外键
  1. 一个表中的字段依赖于另一个表的主键/唯一键;
  2. 保证两张表数据的关联完整性;
  3. 可以设置 级联操作(如删除/更新时一起变化)
-- 创建班级表
CREATE TABLE classes (class_id INT PRIMARY KEY,class_name VARCHAR(100)
);-- 创建学生表,并设置外键关联到班级表
CREATE TABLE students (student_id INT PRIMARY KEY,name VARCHAR(100),class_id INT,FOREIGN KEY (class_id) REFERENCES classes(class_id)
);
2. 约束 vs 索引的区别
项目约束索引
定义整性、合法性加速数据查询效率
主要目的保证正确性(不插错、不留空、不重复)提升性能(更快查找)
本质规则数据结构(如B+树)
关系主键约束、唯一约束会自动生成对应索引!索引不一定带有约束,单纯为了提速
示例NOT NULL、UNIQUE、PRIMARY KEY、FOREIGN KEYCREATE INDEX idx_name ON table(col)

5. 索引实现

1. 索引存储
  1. 索引存储的数据结构通常是 B+树,而不是哈希表
  2. 索引是磁盘上的有序结构,不是存在内存中的
2. 页
  1. innoDB 的数据存储以 页(Page) 为最小单位,每一页大小通常是 16KB。
  2. 一棵 B+ 树的每个节点对应一个或多个磁盘页
  3. 数据读写以页为单位进行(减少磁盘 I/O 次数)
3. B+树
  1. B+树是数据库默认的索引结构
  2. 每个节点存放有序的数据键值+指向子节点的指针
  3. 所有数据都存放在叶子节点
  4. 叶子节点之间有链表连接(范围查询快)
4. B+树层高问题
  1. 理想状态下,B+树的高度很低,一般在 2-4层
  2. 为什么?
    因为一页(16KB)能存很多索引项(假设一项占 16字节,1页能存1024项);所以即使存百万条数据,只要 2-3 次磁盘IO 就能找到,非常快!
5. 自增id
  1. 很多表喜欢用 自增ID(auto_increment) 作为主键。
  2. 自增ID的好处:
    插入数据总是追加到B+树的最右边;
    避免频繁分裂、重排;
    插入性能最好
    放心用,根本用不完
6. 聚集索引
  1. InnoDB 的每张表数据文件本身就是一棵 B+树,称为聚集索引。
  2. 主键索引就是数据本身
  3. 特点:
    按主键顺序存储;
    查找主键非常快;
    非主键(普通索引)存储的是【主键值】作为指针
7. 辅助索引
  1. 除了主键外,创建的其他索引,都是辅助索引
  2. 辅助索引的叶子节点,不直接存储数据行,而是存储【主键值】
  3. 查询时,先通过辅助索引找到主键,再通过主键去聚集索引找完整数据(回表)

总之,索引信息和数据信息的分层管理,便于高效的组织磁盘数据,快速实现单点和范围查询

8. innnodb体系结构

1. buffer pool

Buffer Pool 是 InnoDB 把磁盘上的数据页、索引页、插入缓冲(Change Buffer)、自适应哈希索引等缓存到内存中的区域。
目的是:减少磁盘 I/O,提高数据库访问速度。

特点

  1. 查询数据时优先从 Buffer Pool 取(命中则速度很快)
  2. 如果没有命中,才从磁盘读入,并加入 Buffer Pool(可能引发淘汰机制,比如 LRU)
  3. 包括脏页管理(数据被修改但未刷盘)机制
2. change buffer

Change Buffer 是 InnoDB 中专门为二级索引的插入、更新、删除操作设置的缓存区域,延迟将二级索引变更写入磁盘,从而减少磁盘 I/O。

**原理:

  1. 对于二级索引的插入/修改,不直接去磁盘更新,而是先记录到 Change Buffer。
  2. 之后在一定条件(比如页被读取进内存,或系统空闲时)才真正合并到磁盘上的二级索引页。

为什么只针对二级索引(非主键索引)?

  1. 因为主键索引(聚集索引)必须保证实时一致性。
  2. 二级索引允许延迟一致,所以可以先缓存在 Change Buffer。
CREATE TABLE user (id INT PRIMARY KEY,       -- 主键,主索引name VARCHAR(50),age INT,email VARCHAR(50),INDEX idx_name (name)      -- 二级索引
);
--id 是 主索引(一级索引):--叶子节点:存的是整行数据,比如 {id=1, name="张三", age=20, email="xx@xx.com"}--name 是 辅助索引(二级索引):--叶子节点:只存 {name="张三", id=1}--如果通过 name 查找,还需要根据 id 再去主索引回表拿到完整那一行。

一级索引(主索引):叶子节点存整行

二级索引(辅助索引):叶子节点存主键id,查询时需要回主键索引再拿数据

9. 最左匹配原则

组合索引在查询时,会优先用最左边的列开始匹配,从左到右连续匹配才能用上索引

CREATE INDEX idx_user_name_age ON users(name, age);SELECT * FROM users WHERE name = 'Tom';      --  用上索引
SELECT * FROM users WHERE name = 'Tom' AND age = 18; --  用上索引
SELECT * FROM users WHERE age = 18;           -- 用不了索引(跳过了最左的 name)

10. 覆盖索引

查询的数据只需要索引里的字段,不用回表到原表,因此速度更快

CREATE INDEX idx_name_age ON users(name, age);SELECT name, age FROM users WHERE name = 'Tom'; -- 覆盖索引
--因为 name 和 age 都在 idx_name_age 这个索引里,不需要回表SELECT name FROM users WHERE name = 'Tom';     -- 回表了

11. 索引下推

在索引遍历阶段就尽量筛选数据,减少回表次数,提升查询性能

SELECT * FROM users WHERE name LIKE 'Tom%' AND age = 18;
-- 假设没有索引下推,会先根据 name LIKE 'Tom%' 找到满足条件的索引项,然后再根据 age = 18 进行过滤。-- 而索引下推则是在索引遍历阶段就对 WHERE 条件进行筛选,减少回表次数。
--少了很多不必要的回表

12. 索引失效

一些不合理的 SQL 写法,会导致原本能用的索引失效,导致全表扫描

13. 索引原则

原则内容
最优选择尽量选择区分度高的列建立索引
组合优先多条件查询,建组合索引,遵循最左匹配
覆盖优先尽可能做到查询只用索引(覆盖索引)
更新慎用索引太多,更新、插入性能会变差
合理选择小表不建索引,大表必须优化索引
防止失效避免在索引列上做函数、运算、隐式转换

2. sql比较慢怎么办

1. 慢查询日志

  1. 慢查询日志是 MySQL 提供的一种日志记录机制,用于记录执行时间超过阈值的 SQL 语句。
  2. 可以通过配置来开启慢查询日志,设置阈值,然后查看日志文件来分析哪些 SQL 语句耗时。

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

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

相关文章

【学习笔记】文件包含漏洞--本地远程包含、伪协议、加密编码

一、文件包含漏洞 和SQL等攻击方式一样,文件包含漏洞也是一种注入型漏洞,其本质就是输入一段用户能够控制的脚本或者代码,并让服务端执行。 什么叫包含呢?以PHP为例,我们常常把可重复使用的函数写入到单个文件中&…

蓝桥杯 2021年模拟赛 扫雷问题

题目: 在一个 n 行 m 列的方格图上有一些位置有地雷,另外一些位置为空。 请为每个空位置标一个整数,表示周围八个相邻的方格中有多少个地雷。 输入描述 输入的第一行包含两个整数 n,m。 第 22行到第n1 行每行包含 m 个整数,相…

写windows服务日志-.net4.5.2-定时修改数据库中某些参数

环境: windows 11 Visual Studio 2015 .net 4.5.2 SQL Server 目的: 定时修改数据库中某些参数的值 定时修改24小时内,SQL数据库中,表JD_Reports 内,如果部门是‘体检科,设置打印类型为 1 可以打印。步骤&a…

madvise MADV_FREE对文件页统计的影响及原理

一、背景 madvise系统调用是一个与性能优化强相关的一个系统调用。madvise系统调用包括使用madvise函数,也包含使用posix_fadvise函数。如我们可以使用posix_fadvise传入POSIX_FADV_DONTNEED来清除文件页的page cache以减少内存压力。 这篇博客里,我们…

于键值(KV)的表

基于键值(KV)的表 将行编码为键值(KVs) 索引查询:点查询和范围查询 在关系型数据库中,数据被建模为由行和列组成的二维表。用户通过SQL表达他们的意图,而数据库则神奇地提供结果。不那么神奇的…

2025年邵阳市工程技术研究中心申报流程、条件、奖补

一、邵阳市工程技术研究中心申报条件 (一)工程技术研究中心主要依托科技型企业组建,依托单位应具有以下条件: 1. 具有较强技术创新意识的领导班子和技术水平高、工程化实践经验丰富的工程技术研发队伍,其中固定人员…

Python+AI提示词出租车出行轨迹预测:梯度提升GBR、KNN、LR回归、随机森林融合及贝叶斯概率异常检测研究

原文链接:tecdat.cn/?p41693 在当今数字化浪潮席卷全球的时代,城市交通领域的海量数据如同蕴藏着无限价值的宝藏等待挖掘。作为数据科学家,我们肩负着从复杂数据中提取关键信息、构建有效模型以助力决策的使命(点击文末“阅读原文…

系统重装——联想sharkbay主板电脑

上周给一台老电脑重装系统系统,型号是lenovo sharkbay主板的电脑,趁着最近固态便宜,入手了两块长城的固态,装上以后插上启动U盘,死活进不去boot系统。提示 bootmgr 缺失,上网查了许久,终于解决了…

python连接Elasticsearch并完成增删改查

python库提供了elasticsearch模块,可以通过以下命令进行快速安装,但是有个细节需要注意一下,安装的模块版本要跟es软件版本一致,此处举例:7.8.1 pip install elasticsearch==7.8.1 首先连接elasticsearch,以下是免密示例 from elasticsearch import Elasticsearch# El…

PDF嵌入图片

所需依赖 <dependency><groupId>com.itextpdf</groupId><artifactId>itext-core</artifactId><version>9.0.0</version><type>pom</type> </dependency>源码 /*** PDF工具*/ public class PdfUtils {/*** 嵌入图…

目标检测篇---faster R-CNN

目标检测系列文章 第一章 R-CNN 第二篇 Fast R-CNN 目录 目标检测系列文章&#x1f4c4; 论文标题&#x1f9e0; 论文逻辑梳理1. 引言部分梳理 (动机与思想) &#x1f4dd; 三句话总结&#x1f50d; 方法逻辑梳理&#x1f680; 关键创新点&#x1f517; 方法流程图关键疑问解答…

Seaborn模块练习题

1.使用tips数据集&#xff0c;创建一个展示不同时间段(午餐/晚餐)账单总额分布的箱线图 import seaborn as sns import matplotlib.pyplot as plt import pandas as pdsns.set_style("darkgrid") plt.rcParams["axes.unicode_minus"] Falsetips pd.read…

计算机网络 | 应用层(1)--应用层协议原理

&#x1f493;个人主页&#xff1a;mooridy &#x1f493;专栏地址&#xff1a;《计算机网络&#xff1a;自定向下方法》 大纲式阅读笔记 关注我&#x1f339;&#xff0c;和我一起学习更多计算机的知识 &#x1f51d;&#x1f51d;&#x1f51d; 目录 1. 应用层协议原理 1.1 …

论文导读 - 基于大规模测量与多任务深度学习的电子鼻系统实现目标识别、浓度预测与状态判断

基于大规模测量与多任务深度学习的电子鼻系统实现目标识别、浓度预测与状态判断 原论文地址&#xff1a;https://www.sciencedirect.com/science/article/abs/pii/S0925400521014830 引用此论文&#xff08;GB/T 7714-2015&#xff09;&#xff1a; WANG T, ZHANG H, WU Y, …

React中createPortal 的详细用法

createPortal 是 React 提供的一个实用工具&#xff0c;用于将 React 子元素渲染到 DOM 中的某个位置&#xff0c;而该位置与父组件不在同一个 DOM 层次结构中。这在某些特殊场景下非常有用&#xff0c;比如实现模态框、弹出菜单、固定定位元素等功能。 基本语法 JavaScript …

电池的寿命

思路&#xff1a; 首先&#xff0c;我们观察发现&#xff1a;由于每枚电池的使用时间不同&#xff0c;而我们又要减少浪费才能使所有电池加起来用得最久&#xff0c;不难发现&#xff1a;当n2时&#xff0c;输出较小值。 第一步&#xff1a;将电池分为两组&#xff0c;使两组…

LeetCode每日一题4.27

3392. 统计符合条件长度为 3 的子数组数目 问题 问题分析 统计符合条件的长度为 3 的子数组数目。具体条件是&#xff1a;子数组的第一个数和第三个数的和恰好为第二个数的一半。 思路 遍历数组&#xff1a;由于子数组长度固定为 3&#xff0c;我们可以通过遍历数组来检查每…

Linux日志处理命令多管道实战应用

全文目录 1 日志处理1.1 实时日志分析1.1.1 nginx日志配置1.1.2 nginx日志示例1.1.3 日志分析示例 1.2 多文件合并分析1.3 时间范围日志提取 2 问题追查2.1 进程级问题定位2.2 网络连接排查2.3 硬件故障追踪 3 数据统计3.1 磁盘空间预警3.2 进程资源消耗排名3.3 HTTP状态码统计…

0803分页_加载更多-网络ajax请求2-react-仿低代码平台项目

文章目录 1 分页1.1 url与分页参数1.2 分页组件与url1.3 列表页引用分页组件 2 加载更多2.1 状态2.2 触发时机2.3 加载数据2.4优化 结语 1 分页 1.1 url与分页参数 查询问卷列表接口&#xff0c;添加分页参数&#xff1a; page&#xff1a;当前页码&#xff08;第几页&#…

【技术追踪】基于扩散模型的脑图像反事实生成与异常检测(TMI-2024)

一种新颖的扩散模型双重采样策略&#xff0c;DDPM DDIM ~ 论文&#xff1a;Diffusion Models for Counterfactual Generation and Anomaly Detection in Brain Images 0、摘要 病理区域的分割掩模在许多医学应用中很有用&#xff0c;例如脑肿瘤和中风管理。此外&#xff0c;疾…