MySQL 中 6 种索引访问类型的完整方案
通过 EXPLAIN 分析后,可针对性优化索引策略:
博主介绍:✌全网粉丝5W+,全栈开发工程师,从事多年软件开发,在大厂呆过。持有软件中级、六级等证书。可提供微服务项目搭建与毕业项目实战,博主也曾写过优秀论文,查重率极低,在这方面有丰富的经验✌
博主作品:《Java项目案例》主要基于SpringBoot+MyBatis/MyBatis-plus+MySQL+Vue等前后端分离项目,可以在左边的分类专栏找到更多项目。《Uniapp项目案例》有几个有uniapp教程,企业实战开发。《微服务实战》专栏是本人的实战经验总结,《Spring家族及微服务系列》专注Spring、SpringMVC、SpringBoot、SpringCloud系列、Nacos等源码解读、热门面试题、架构设计等。除此之外还有不少文章等你来细细品味,更多惊喜等着你哦
🍅uniapp微信小程序🍅面试题软考题免费使用,还可以使用微信支付,扫码加群。由于维护成本问题得不到解决,可能将停止线上维护。
🍅文末获取联系🍅精彩专栏推荐订阅👇🏻👇🏻 不然下次找不到哟
Java项目案例《100套》
https://blog.csdn.net/qq_57756904/category_12173599.html
uniapp小程序《100套》https://blog.csdn.net/qq_57756904/category_12173599.html
有需求代码永远写不完,而方法才是破解之道,抖音有实战视频课程,某马某千等培训都是2万左右,甚至广东有本科院校单单一年就得3万4年就12万学费,而且还没有包括吃饭的钱。所以很划算了。另外博客左侧有源码阅读专栏,对于求职有很大帮助,当然对于工作也是有指导意义等。在大城市求职,你面试来回一趟多多少少都在12块左右,而且一般不会一次性就通过,还得面试几家。而如果你对源码以及微服务等有深度认识,这无疑给你的面试添砖加瓦更上一层楼。
最后再送一句:最好是学会了,而不是学废了!!
2
以下是建表、创建索引及模拟不同访问类型的详细操作步骤:
-- 创建测试表
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT, -- 主键列
username VARCHAR(50) NOT NULL, -- 用户名
email VARCHAR(100) NOT NULL, -- 邮箱
age INT NOT NULL, -- 年龄
created_at DATETIME DEFAULT CURRENT_TIMESTAMP -- 创建时间
);
-- 插入测试数据
INSERT INTO users (username, email, age)
VALUES
('john_doe', 'john@example.com', 28),
('jane_smith', 'jane@test.com', 32),
('bob_johnson', 'bob@mail.com', 45),
('alice_wonder', 'alice@domain.com', 23),
('john_doe', 'john2@site.com', 31); -- 故意插入重复用户名
-- 添加额外索引
ALTER TABLE users ADD INDEX idx_username (username); -- 普通索引
ALTER TABLE users ADD INDEX idx_age (age); -- 普通索引
ALTER TABLE users ADD UNIQUE INDEX uniq_email (email); -- 唯一索引
模拟 6 种访问类型场景
1. ALL - 全表扫描
-- 场景:无索引条件查询
EXPLAIN SELECT * FROM users WHERE created_at > '2023-01-01';
结果特征:
-
type: ALL
-
key: NULL
-
rows: 5
(全表行数)
2. INDEX - 全索引扫描
-- 场景:仅查询索引列(覆盖索引)
EXPLAIN SELECT username FROM users;
结果特征:
-
type: index
-
key: idx_username
-
Extra: Using index
3. RANGE - 索引范围扫描
-- 场景:使用范围查询 EXPLAIN SELECT * FROM users WHERE age BETWEEN 20 AND 30;
结果特征:
-
type: range
-
key: idx_age
-
Extra: Using index condition
4. REF - 非唯一索引查找
-- 场景:使用普通索引等值查询(username 有重复值)
EXPLAIN SELECT * FROM users WHERE username = 'john_doe';
结果特征:
-
type: ref
-
key: idx_username
-
rows: 2
(返回匹配行数)
5. EQ_REF - 唯一索引查找
-- 创建关联表
CREATE TABLE orders (
order_id INT PRIMARY KEY,
user_email VARCHAR(100),
amount DECIMAL(10,2)
);
-- 添加外键关联
ALTER TABLE orders ADD CONSTRAINT fk_user_email
FOREIGN KEY (user_email) REFERENCES users(email);
-- 模拟场景:多表关联(唯一索引)
EXPLAIN SELECT *
FROM users
JOIN orders ON users.email = orders.user_email;
结果特征:
-
type: eq_ref
-
key: uniq_email
-
Extra: Using index
6. CONST - 主键/唯一索引单行查找
-- 场景:主键等值查询
EXPLAIN SELECT * FROM users WHERE id = 3;
结果特征:
-
type: const
-
key: PRIMARY
-
rows: 1
验证结果对照表
访问类型 | 触发条件 | 关键特征 |
---|---|---|
ALL |
无可用索引的查询 | key: NULL , 扫描全表 |
INDEX |
仅查询索引列的覆盖索引 | Extra: Using index |
RANGE |
BETWEEN , > , < 等 |
使用范围索引扫描 |
REF |
普通索引的等值查询 | 非唯一查找,可能多行匹配 |
EQ_REF |
多表关联时唯一索引匹配 | 每行只匹配一个关联行 |
CONST |
主键/唯一索引的单行查询 | 最多返回一行,效率最高 |
优化建议:
-
避免 ALL 扫描:为核心查询字段创建索引
-
利用覆盖索引:减少
SELECT *
,只查询必要字段 -
范围查询优化:对范围列单独建索引,避免组合索引失效
-
EQ_REF 场景:确保关联字段有唯一索引
-
CONST 优先:高频查询尽量通过主键/唯一键访问
通过 EXPLAIN
分析后,可针对性优化索引策略:
-- 查看执行计划详情
EXPLAIN FORMAT=JSON SELECT ...
-- 检查索引使用情况
SELECT * FROM sys.schema_index_statistics
WHERE table_name = 'users';
更多推荐
所有评论(0)