常见的数据访问方法
约 898 字大约 3 分钟
常见的数据访问方法
在 MySQL 和 Oracle 中使用 EXPLAIN
分析 SQL 查询时,索引访问方法(也叫访问路径)是优化 SQL 性能的关键。不同的索引访问方式直接影响查询效率,
下面我们详细讲解 MySQL 和 Oracle 中可能出现的各种索引访问方式,便于你更好地理解和优化 SQL。
✅ 一、MySQL 索引访问方法(重点看 type
字段)
在 EXPLAIN
输出中,type
表示 访问类型(access type),从好到坏排列如下:
type | 说明 | 是否使用索引 | 备注 |
---|---|---|---|
system | 表仅有一行,系统表 | 否 | 极少出现 |
const | 通过主键或唯一索引查询常量值 | 是 | 查询结果最多一行 |
eq_ref | 每次只返回一条匹配记录 | 是 | 用于主键或唯一索引连接 |
ref | 非唯一索引匹配,可能返回多行 | 是 | 最常见的索引连接类型 |
fulltext | 全文索引搜索 | 是 | 用于 MATCH() AGAINST() |
ref_or_null | ref 扫描 + NULL 检查 | 是 | 少见 |
index_merge | 合并多个索引 | 是 | 会显示使用了哪几个索引 |
range | 范围扫描(BETWEEN、>、<、IN) | 是 | 使用索引的区间查询 |
index | 遍历整个索引(不访问表) | 是 | 相比 ALL 效率稍高 |
ALL | 全表扫描 | 否 | 最低效,尽量避免 |
🔍 示例说明:
-- const 类型
SELECT * FROM users WHERE id = 1; -- 主键查询
-- eq_ref 类型
SELECT * FROM orders o JOIN users u ON o.user_id = u.id;
-- ref 类型
SELECT * FROM users WHERE name = 'Tom'; -- name 上有普通索引
-- range 类型
SELECT * FROM users WHERE age BETWEEN 20 AND 30;
-- index_merge 类型
SELECT * FROM users WHERE name = 'Tom' OR age = 30; -- name 和 age 上都有索引
✅ 二、Oracle 索引访问方法(重点看 Operation
+ Options
)
在 Oracle 中使用 EXPLAIN PLAN
或 DBMS_XPLAN.DISPLAY()
查看执行计划,关注以下访问方法:
Operation + Options | 描述 | 是否回表 | 性能 |
---|---|---|---|
INDEX UNIQUE SCAN | 唯一索引精确匹配 | 可能 | 非常快 |
INDEX RANGE SCAN | 范围扫描 | 可能 | 高效 |
INDEX FULL SCAN | 全索引扫描(顺序遍历整个索引) | 否 | 一般用于避免排序或覆盖索引 |
INDEX FAST FULL SCAN | 快速索引全扫描(随机读) | 否 | 不保证顺序,适合覆盖索引 |
INDEX SKIP SCAN | 跳跃扫描 | 是 | 比全表快,低于 range |
BITMAP INDEX SCAN | 位图索引扫描 | 是 | 适合多条件查询 |
TABLE ACCESS BY INDEX ROWID | 回表取数据 | 是 | 索引不覆盖字段时发生 |
TABLE ACCESS FULL | 全表扫描 | 否 | 最慢,优化重点 |
🔍 示例说明:
-- 唯一索引扫描(INDEX UNIQUE SCAN)
SELECT * FROM employees WHERE emp_id = 100;
-- 范围索引扫描(INDEX RANGE SCAN)
SELECT * FROM employees WHERE hire_date > TO_DATE('2020-01-01', 'YYYY-MM-DD');
-- 全索引扫描(INDEX FULL SCAN)
SELECT emp_id FROM employees ORDER BY emp_id;
-- 快速全索引扫描(INDEX FAST FULL SCAN)
SELECT emp_id FROM employees; -- emp_id 是索引列,且覆盖查询
-- 跳跃扫描(INDEX SKIP SCAN)
SELECT * FROM employees WHERE department_id = 10;
-- 若有 (last_name, department_id) 的组合索引,但未用最左列
🆚 MySQL 与 Oracle 索引访问方式对照表:
MySQL type | Oracle Operation | 相似含义说明 |
---|---|---|
const | INDEX UNIQUE SCAN | 主键/唯一值查询 |
eq_ref | INDEX UNIQUE SCAN + TABLE ACCESS BY INDEX ROWID | 唯一值关联 |
ref | INDEX RANGE SCAN | 普通索引查找 |
range | INDEX RANGE SCAN | 范围条件 |
index | INDEX FULL SCAN | 遍历索引全部值 |
ALL | TABLE ACCESS FULL | 全表扫描 |
🧠 小结优化建议:
- 首选访问方式:MySQL 中尽量让
type
为const
,eq_ref
,ref
, Oracle 中优选INDEX UNIQUE/RANGE SCAN
。 - 避免访问方式:
ALL
(MySQL)或TABLE ACCESS FULL
(Oracle),会导致全表扫描。 - 索引设计要点:
- 保证选择性高的列建索引
- 组合索引遵守最左前缀原则
- 查询字段尽量使用覆盖索引
- 尽量避免对索引列使用函数或类型转换