索引
SELECT TABLE_NAME, INDEX_NAME, COLUMN_NAME FROM INFORMATION_SCHEMA.STATISTICS WHERE TABLE_SCHEMA = 'your_database_name' and TABLE_NAME like '%table_name%';
索引失效的场景
假设场景
CREATE TABLE test ( id bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '数据ID,主键自增', age bigint unsigned NOT NULL DEFAULT ' ' COMMENT '年龄', name varchar(100) NOT NULL DEFAULT '0' COMMENT '名称', createTime char(14) NOT NULL DEFAULT ' ' COMMENT '创建时间,yyyyMMddHHmmss', createUserId bigint unsigned NOT NULL DEFAULT '0' COMMENT '创建用户ID', updateTime char(17) NOT NULL DEFAULT ' ' COMMENT '修改时间,yyyyMMddHHmmssSSS', updateUserId bigint unsigned NOT NULL DEFAULT '0' COMMENT '修改用户ID', deleted tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '是否逻辑删除。 [0:否, 1:是]', PRIMARY KEY (id), INDEX idxAge (age, name), INDEX idxCreateTime (createTime), ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COMMENT ='测试';
- 违反最左前缀原则(联合索引)
- 解释:只有当查询条件使用到索引最左边的字段 a时,索引才会被使用。
-
explain select * from test where name="1"
- 在索引列使用函数运算
-
explain select * from test where substr(name,1,3)="123";
-
- 索引列使用范围查询
- 数据量大时会失效
- is not null会失效
-
explain select * from test where age is not null;
-
- not in会失效
-
explain select * from test where age is not null;
-
- not exists 会失效
- 使用or可能会失效
- 使用or连接到非索引列会失效
- 索引使用通配符查询,且通配符在前面
-
explain select * from test where createTime like '%123%'
-
- 触发隐式转换——索引是字符类型,且没有加双引号,可能会失效,
-
explain select * from test where createTime =123
-
- 如果查询结果集中的列数超过了索引列数,则索引 可能 失效。这是因为 MySQL 在查询结果集时,需要从索引中提取额外的列值,这会降低索引的使用效率。
- 两列比较
-
explain select * from test where age >id
-
- 不使用select * 可以走覆盖索引
-
explain select id from test where name="1"
-
- 使用ordre by(使用id的话会走索引)
-
explain select * from test order by age
-
查询速度排序(从快到慢):
const>eq_ref>ref>range>index>ALL
const 常量级
查询条件是一个常量时,MySQL 可以快速确定只有一行数据匹配。最快的查询类型(一般命中唯一索引和主键)
select id form test where id=1
eq_ref 索引查询(比ref快)
explain
select *
from test a
left join test2 b on a.id = b.tId
where a.id in (1,2);
使用唯一主键查询
ref 索引查询
select id from test where age=1
使用非唯一主键查询,返回单独一行数据
range索引范围查询
select id from test where age in(1,2)
常见于 '<', '<=', '>', '>=', 'between' ,in等范围行函数和操作符.
index全索引查询(和all的区别在于index是遍历了所有查询索引树)
select id from test
ALL全表查询(最慢的查询,未使用到索引)
select * from test
执行方式
大部分情况下为串行
- 若版本 >= 8.0.14:默认支持 InnoDB 并行扫描,通过
innodb_parallel_read_threads配置。 - 若版本 >= 8.0.27:可实验性启用并行查询(需手动配置)。
- 并行复制:所有 5.7+ 版本均支持,但需配置
slave_parallel_workers > 0。
多个sql 的情况下
- MySQL 默认支持 多线程处理多个连接,因此这些 SQL 会并行执行(每个连接分配独立线程)。
- 可能串行化的场景:
- 全局资源争用:如磁盘 I/O 饱和、InnoDB 缓冲池竞争。
- 表级锁(仅限 MyISAM):MyISAM 引擎对写操作默认加表级锁,若两个线程同时写不同 MyISAM 表,仍可能因全局锁调度串行化。
- 行级锁冲突(InnoDB):若不同表的操作涉及同一事务或隐式锁(如外键约束),可能间接导致串行化。
单个sql结合多个表时
- MySQL 在大多数情况下(尤其是 8.0 之前版本)会串行执行 JOIN 和子查询,由单个线程处理所有步骤。
- MySQL 8.0+ 并行查询:
若启用parallel_query实验性功能(需配置parallel_query_threads),优化器可能将大表的扫描或聚合拆分为并行任务。-- 查看是否启用并行查询 SHOW VARIABLES LIKE 'parallel_query%';
- InnoDB 并行索引扫描(8.0.14+):
对大表的全索引扫描或范围扫描可能触发多线程并行读取(通过innodb_parallel_read_threads配置)。-- 查看并行扫描线程数 SHOW VARIABLES LIKE 'innodb_parallel_read_threads';
不同存储引擎的差异
| 存储引擎 | 并行能力 | 说明 |
|---|---|---|
| InnoDB | 支持部分并行 | 8.0+ 支持并行索引扫描和实验性并行查询 |
| MyISAM | 仅串行 | 所有操作串行执行,写操作默认加表级锁 |
| Memory | 串行 | 无并行优化 |
如何验证是否为并行
监控线程活动
-- 查看正在执行的线程(观察多个线程是否处理同一查询) SHOW PROCESSLIST; -- 通过 Performance Schema 监控并行线程 SELECT * FROM performance_schema.threads WHERE NAME LIKE '%parallel%' OR NAME LIKE '%worker%';
分析执行计划
使用 EXPLAIN FORMAT=TREE 查看是否触发并行执行:
EXPLAIN FORMAT=TREE SELECT * FROM large_table WHERE col > 100;
- 若输出中包含
parallel scan或并发线程数标记(如workers=4),表示触发了并行扫描。
观察资源使用
- CPU 利用率:并行查询会显著提升多核 CPU 使用率。
- I/O 吞吐量:并行扫描可能增加磁盘读吞吐。
关键配置参数
| 参数 | 作用 | 建议值 |
|---|---|---|
innodb_parallel_read_threads |
InnoDB 并行扫描线程数 | 根据 CPU 核心数调整(通常 4-8) |
parallel_query_threads |
并行查询线程数(8.0.27+) | 实验性功能,谨慎启用 |
slave_parallel_workers |
从库并行复制线程数 | 主从场景下建议设置为 CPU 核心数 50%~75% |
总结
- 不同 SQL 操作不同表:
- 默认并行(多线程处理不同连接),但受全局资源或锁竞争影响。
- 单条 SQL 涉及多表:
- 串行为主,8.0+ 版本可通过并行扫描或实验性并行查询优化部分场景。
- 存储引擎限制:
- InnoDB 支持有限并行,MyISAM 完全串行。
建议:
- 升级到 MySQL 8.0+ 并合理配置
innodb_parallel_read_threads。 - 对复杂查询使用
EXPLAIN FORMAT=TREE验证是否触发并行。 - 避免 MyISAM 表在高并发场景中使用。
未完
- THE END -
最后修改:2025年3月11日
非特殊说明,本博所有文章均为博主原创。
如若转载,请注明出处:https://jiaheming.cn/2024/05/mysql%e7%9a%84%e7%b4%a2%e5%bc%95/

共有 0 条评论