当前位置: 首页 > news >正文

Mysql——索引

Mysql——索引

    • 索引
      • 优缺点:
      • 索引结构
      • 索引分类
        • 聚集索引选取规则:
        • 语法
        • 使用规则
        • 索引失效情况
        • 覆盖索引
      • SQL 优化
        • order by优化
        • group by优化

索引

索引是帮助 MySQL 高效获取数据的一种数据结构。

优缺点:

  • 优点:
    提高数据检索效率,降低数据库的IO成本
    通过索引列对数据进行排序,降低数据排序的成本,降低CPU的消耗
  • 缺点:
    索引列也是要占用空间的
    索引大大提高了查询效率,但降低了更新的速度,比如 INSERT、UPDATE、DELETE

索引结构

MySQL 索引数据结构对经典的 B+Tree 进行了优化。在原来 B-Tree 的基础上,增加一个指向相邻叶子节点的链表指针,就形成了带有顺序指针的 B+Tree,提高区间访问的性能。
在这里插入图片描述

演示地址

索引分类

分类含义特点关键字
主键索引针对于表中主键创建的索引 默认自动创建,只能有一个PRIMARY
唯一索引避免同一个表中某数据列中的值重复可以有多个UNIQUE
常规索引快速定位特定数据可以有多个
全文索引全文索引查找的是文本中的关键词,而不是比较索引中的值可以有多个FULLTEXT

在 InnoDB 存储引擎中,根据索引的存储形式,又可以分为以下两种:

分类含义特点
聚集索引(Clustered Index)将数据存储与索引放一块,索引结构的叶子节点保存了行数据必须有,而且只有一个(叶子节点存储整行的数据)
二级索引(Secondary Index)将数据与索引分开存储,索引结构的叶子节点关联的是对应的主键可以存在多个(叶子节点存储id)
聚集索引选取规则:

如果存在主键,主键索引就是聚集索引
如果不存在主键,将使用第一个唯一(UNIQUE)索引作为聚集索引
如果表没有主键或没有合适的唯一索引,则 InnoDB 会自动生成一个 rowid 作为隐藏的聚集索引

语法
创建索引:
CREATE [ UNIQUE | FULLTEXT ] INDEX index_name ON table_name (index_col_name, ...);
如果不加 CREATE 后面不加索引类型参数,则创建的是常规索引

查看索引:
SHOW INDEX FROM table_name;

删除索引:
DROP INDEX index_name ON table_name;

案例:

-- name字段为姓名字段,该字段的值可能会重复,为该字段创建索引
create index idx_user_name on tb_user(name);
-- phone手机号字段的值非空,且唯一,为该字段创建唯一索引
create unique index idx_user_phone on tb_user (phone);
-- 为profession, age, status创建联合索引
create index idx_user_pro_age_stat on tb_user(profession, age, status);
-- 为email建立合适的索引来提升查询效率
create index idx_user_email on tb_user(email);

-- 删除索引
drop index idx_user_email on tb_user;
使用规则
  • 最左前缀法则

如果索引关联了多列(联合索引),要遵守最左前缀法则,最左前缀法则指的是查询从索引的最左列开始,并且不跳过索引中的列。

create index idx_stu_age_sex_country on stu (country,age,sex);


EXPLAIN SELECT * FROM stu WHERE country = 'China' AND age = 14 AND sex = 'Male'

如果跳跃某一列,索引将部分失效(后面的字段索引失效)。

联合索引中,出现范围查询(<, >),范围查询右侧的列索引失效。可以用>=或者<=来规避索引失效问题。

create index idx_stu_name_age_phone on stu (name,age,phone);
EXPLAIN SELECT * FROM stu WHERE name = 'Student16' AND age >= 16 AND phone = '12328557947'
create index idx_stu_age_sex_country on stu (country,age,sex);

EXPLAIN SELECT * FROM stu WHERE country = 'China' AND age = 14 AND sex = 'Male'
索引失效情况
  • 在索引列上进行运算操作,索引将失效。如:
explain select * from stu where substring(phone, 10, 2) = '15';
  • 字符串类型字段使用时,不加引号,索引将失效。如:
explain select * from stu where phone = 17799990015;
  • 模糊查询中,如果仅仅是尾部模糊匹配,索引不会是失效;
  • 前后都有 % 也会失效。
  • 如果是头部模糊匹配,索引失效。如:
explain select * from stu where phone like '%16754'
  • 用 or 分割开的条件,如果 or 其中一个条件的列没有索引,那么涉及的索引都不会被用到。
explain select * from stu where phone = '11955716754' or name = 'Student35' OR id_card_num = '313703455'

如果 MySQL 评估使用索引比全表更慢,则不使用索引。

覆盖索引

如果在聚集索引中直接能找到对应的行,则直接返回行数据,只需要一次查询,哪怕是select *;如果在辅助索引中找聚集索引,如select id, name from xxx where name=‘xxx’;,也只需要通过辅助索引(name)查找到对应的id,返回name和name索引对应的id即可,只需要一次查询;如果是通过辅助索引查找其他字段,则需要回表查询,如
select id, name, gender from xxx where name=‘xxx’;

所以尽量不要用select *,容易出现回表查询,降低效率,除非有联合索引包含了所有字段

SQL 优化

order by优化
  1. Using filesort:通过表的索引或全表扫描,读取满足条件的数据行,然后在排序缓冲区 sort buffer 中完成排序操作,所有不是通过索引直接返回排序结果的排序都叫 FileSort 排序
  2. Using index:通过有序索引顺序扫描直接返回有序数据,这种情况即为 using index,不需要额外排序,操作效率高

如果order by字段全部使用升序排序或者降序排序,则都会走索引,但是如果一个字段升序排序,另一个字段降序排序,则不会走索引,explain的extra信息显示的是Using index, Using filesort,如果要优化掉Using filesort,则需要另外再创建一个索引,如:

create index idx_stu_age_phone on stu(age , phone );

EXPLAIN SELECT age,phone FROM stu ORDER BY age ASC,phone DESC
create index idx_stu_age_phone on stu(age ASC, phone DESC);

此时使用select id, age, phone from tb_user order by age asc, phone desc;会全部走索引

总结:

  • 根据排序字段建立合适的索引,多字段排序时,也遵循最左前缀法则
  • 尽量使用覆盖索引
  • 多字段排序,一个升序一个降序,此时需要注意联合索引在创建时的规则(ASC/DESC)
group by优化
  • 在分组操作时,可以通过索引来提高效率
SELECT address,count(1) FROM stu GROUP BY address
  • 分组操作时,索引的使用也是满足最左前缀法则的
EXPLAIN SELECT address,count(1),school FROM stu GROUP BY address,school

#### update优化(避免行锁升级为表锁)

InnoDB 的行锁是针对索引加的锁,不是针对记录加的锁,并且该索引不能失效,否则会从行锁升级为表锁。

如以下两条语句:

```sql
//这句由于id有主键索引,所以只会锁这一行;
update user set no = '123' where id = 7;

//这句由于name没有索引,所以会把整张表都锁住进行数据更新,解决方法是给name字段添加索引
update student set no = '123' where name = 'test';

相关文章:

  • 网工面试题(安全)
  • 【MySQL篇】表的操作
  • 用pyside6创建一个界面并实现一个小功能且能打包成问题记录
  • ${sym} 与 String(sym) 的区别
  • 《昇腾推理服务器+DeepSeek大模型》技术培训在图为科技成功举办
  • ubuntu终端指令集 shell编程基础(一)
  • 20.<Spring图书管理系统①(登录+添加图书)>
  • 什么是FPGA?
  • 代码随想录算法训练营第十一天| 150. 逆波兰表达式求值,239. 滑动窗口最大值
  • 26.贪心算法4
  • Vue 路由基础:Vue 2 和 Vue 3 的比较与使用
  • APP自动化实战
  • c++ 三维图形 R树的简单应用案例
  • 鸿蒙5.0实战案例:基于RichEditor的评论编辑
  • 鸿道Intewell操作系统的Linux实时拓展方案
  • 组态软件在物联网中的应用
  • TFChat:腾讯大模型知识引擎(DeepSeek R1)+飞书机器人实现AI智能助手
  • Java中的缓存技术:Guava Cache vs Caffeine vs Redis
  • w803|联盛德|WM IoT SDK2.X测试|window11|VSCODE|(4):IDE配置
  • Spark内存迭代计算
  • 软件开发大概需要多少钱/西安seo站内优化
  • 美国新闻网站app/西安今天出大事
  • 如何做监控网站/龙泉驿网站seo
  • 济南网站建设求职/网站建设黄页免费观看
  • 深圳网站建设乐云seo/推广引流吸引人的文案
  • 青龙建站网/1688关键词排名查询