联合索引列序应按WHERE中等值条件优先、范围条件靠后排列,依据选择性与使用频率而非重要性;Oracle 11g对NULL处理严格,12c起支持部分NULL索引;避免盲目创建多列索引,需结合执行计划与实际查询路径分析。
CREATE INDEX 语句中多列顺序怎么排
列顺序直接决定索引能否被 where 条件命中,不是按字段重要性排,而是按查询过滤的「选择性 + 使用频率」组合排。最常出现在 where 开头、且值分布越分散(比如 order_id 比 status 更分散)的列放最左。
- 错误写法:
CREATE INDEX idx_status_time ON orders(status, create_time)—— 如果查询只用了create_time > SYSDATE-7,这个索引完全用不上 - 正确思路:先看执行计划里
WHERE子句实际怎么写的,把等值条件(=)列放前面,范围条件(>,BETWEEN)放后面 - 注意
IN算等值条件,但多个值时效果弱于单个=;IS NULL在 Oracle 12c+ 才能走联合索引最左列
Oracle 11g 和 12c+ 对 NULL 值的处理差异
联合索引默认跳过全为 NULL 的行,但具体行为在版本间有变化,尤其影响 IS NULL 查询是否走索引。
- 11g 及更早:只要联合索引第一列是
NULL,整行不进索引;即使第二列有值也无效 - 12c 引入
INDEXING ON语法,可显式开启对 NULL 的索引支持,但仅限函数索引或带常量的表达式,比如:CREATE INDEX idx_on_null ON t1(nvl(status, 'UNK')) - 如果业务必须查
WHERE col1 IS NULL AND col2 = 'X',别依赖联合索引,改用函数索引或加一个非空标记列
可视化工具(如 SQL Developer)建联合索引的隐藏限制
图形界面点点点很省事,但容易漏掉关键选项,导致生成的 DDL 不符合预期。
- SQL Developer 的「Create Index」向导默认勾选
Include all columns in index,但不会自动排序——你拖拽列的顺序 ≠ 最终 DDL 中的列序,得手动在「Columns」列表里上下调整 - 「Storage」页里的
Tablespace默认填的是用户默认表空间,不是索引专用表空间;线上环境务必改成独立的INDX表空间,避免和数据争 IO - 勾选
Enable monitoring会触发V$OBJECT_USAGE记录,但监控本身有开销,上线后记得关掉:ALTER INDEX idx_name NOMONITORING USAGE
什么时候不该建多列联合索引
不是所有多条件查询都适合上联合索引,盲目添加反而拖慢写性能、撑大内存占用。
- 表更新频繁但查询极少(比如日志表),优先考虑分区裁剪,而不是索引
- 两列相关性极高(比如
country_code和currency总是一一对应),建单列索引 + 配合统计信息通常比联合索引更高效 - 存在前导模糊查询:
WHERE name LIKE '%abc%'—— 即使它在联合索引第一位,整个索引对这个条件也无效 - 已有单列索引覆盖了大部分查询路径,再加联合索引前先跑一遍
DBMS_STATS.REPORT_INDEX_STATS,确认当前索引真的没被复用
联合索引的列数上限是 32,但超过 4 列基本就该怀疑设计了;真正难的是判断哪些查询路径互相冲突,没法被同一个索引覆盖——这时候得看真实执行计划里的 ACCESS PREDICATES 和 FILTER PREDICATES 分别是什么。










