在日常数据库运维工作中,索引管理是性能调优的核心环节。无论是进行迁移评估、性能分析,还是健康检查,快速掌握用户或实例下所有表的索引分布情况都是首要任务。以下汇总了10个可直接复用的Oracle索引查询脚本,涵盖基本信息统计、无索引表发现、大表监控、索引使用分析等常见场景。每个脚本均附有说明注释,方便按需调整。
1. 查询当前用户下所有表的索引数量统计

SELECT t.table_name, COUNT(i.index_name) as index_count, LISTAGG(i.index_name, ', ') WITHIN GROUP (ORDER BY i.index_name) as index_names FROM user_tables t LEFT JOIN user_indexes i ON t.table_name = i.table_name GROUP BY t.table_name ORDER BY COUNT(i.index_name) DESC, t.table_name;
2. 查询所有用户下所有表的索引数量(需DBA权限)
SELECT i.table_owner, i.table_name, COUNT(i.index_name) as index_count, LISTAGG(i.index_name, ', ') WITHIN GROUP (ORDER BY i.index_name) as index_names
FROM dba_indexes i
WHERE i.table_owner NOT IN ('SYS', 'SYSTEM', 'XDB', 'CTXSYS', 'MDSYS', 'ORDSYS') -- 排除系统用户
GROUP BY i.table_owner, i.table_name
ORDER BY i.table_owner, COUNT(i.index_name) DESC, i.table_name;
3. 查询表及索引详细信息(适用于Oracle迁移至TiDB场景)——快速掌握待迁移生产表的行数、唯一索引等关键信息
SELECT t.owner, t.table_name, t.num_rows as table_rows, COUNT(i.index_name) as total_indexes, SUM(CASE WHEN i.uniqueness = 'UNIQUE' THEN 1 ELSE 0 END) as unique_indexes, SUM(CASE WHEN i.uniqueness = 'NONUNIQUE' THEN 1 ELSE 0 END) as nonunique_indexes, SUM(CASE WHEN i.index_type = 'FUNCTION-BASED NORMAL' THEN 1 ELSE 0 END) as function_based_indexes FROM dba_tables t LEFT JOIN dba_indexes i ON t.owner = i.table_owner AND t.table_name = i.table_name WHERE t.owner = 'YOUR_SCHEMA_NAME' -- 替换为你的模式名 GROUP BY t.owner, t.table_name, t.num_rows ORDER BY COUNT(i.index_name) DESC, t.table_name;
4. 按索引类型分组统计
SELECT i.table_owner, i.table_name, i.index_type, COUNT(*) as count_per_type, LISTAGG(i.index_name, ', ') WITHIN GROUP (ORDER BY i.index_name) as index_list FROM dba_indexes i WHERE i.table_owner = 'YOUR_SCHEMA_NAME' -- 替换为你的模式名 GROUP BY i.table_owner, i.table_name, i.index_type ORDER BY i.table_name, i.index_type;
5. 查找没有索引的表(含当前用户与全部用户两种场景)
-- 查找当前用户下没有索引的表
SELECT t.table_name, t.num_rows, t.blocks
FROM user_tables t
WHERE NOT EXISTS (
SELECT 1
FROM user_indexes i
WHERE i.table_name = t.table_name
)
AND t.table_name NOT LIKE 'BIN$%' -- 排除回收站中的表
ORDER BY t.num_rows DESC NULLS LAST;
-- 查找所有用户下没有索引的表(需要DBA权限)
SELECT t.owner, t.table_name, t.num_rows
FROM dba_tables t
WHERE NOT EXISTS (
SELECT 1
FROM dba_indexes i
WHERE i.table_owner = t.owner
AND i.table_name = t.table_name
)
AND t.owner NOT IN ('SYS', 'SYSTEM', 'XDB')
AND t.table_name NOT LIKE 'BIN$%'
ORDER BY t.owner, t.num_rows DESC NULLS LAST;
6. 统计每个索引包含的列数及明细
-- 统计每个索引的列数 SELECT i.table_name, i.index_name, i.uniqueness, i.status, COUNT(ic.column_position) as column_count, LISTAGG(ic.column_name, ', ') WITHIN GROUP (ORDER BY ic.column_position) as columns FROM user_indexes i JOIN user_ind_columns ic ON i.index_name = ic.index_name GROUP BY i.table_name, i.index_name, i.uniqueness, i.status ORDER BY i.table_name, i.index_name;
7. 实用的索引汇总查询:平均高度、叶子块及无效索引统计
-- 索引统计汇总
WITH index_stats AS (
SELECT
owner,
table_name,
COUNT(*) as total_indexes,
ROUND(A VG(blevel), 2) as a vg_blevel,
ROUND(A VG(leaf_blocks), 2) as a vg_leaf_blocks,
SUM(CASE WHEN status != 'VALID' THEN 1 ELSE 0 END) as invalid_indexes
FROM dba_indexes
WHERE owner = 'YOUR_SCHEMA_NAME'
GROUP BY owner, table_name
)
SELECT
owner,
COUNT(DISTINCT table_name) as tables_with_indexes,
SUM(total_indexes) as total_index_count,
ROUND(A VG(total_indexes), 2) as a vg_indexes_per_table,
ROUND(MEDIAN(total_indexes), 2) as median_indexes_per_table,
MAX(total_indexes) as max_indexes_in_table,
SUM(invalid_indexes) as total_invalid_indexes
FROM index_stats
GROUP BY owner;
8. 生产环境监控:检测大表(行数超万)缺少索引的情况
-- 查找行数超过10000但索引数少于2个的表 SELECT t.owner, t.table_name, t.num_rows, COUNT(i.index_name) as index_count FROM dba_tables t LEFT JOIN dba_indexes i ON t.owner = i.table_owner AND t.table_name = i.table_name WHERE t.num_rows > 10000 AND t.owner = 'YOUR_SCHEMA_NAME' GROUP BY t.owner, t.table_name, t.num_rows HA VING COUNT(i.index_name) < 2 ORDER BY t.num_rows DESC;
9. 查看索引使用情况(Oracle 11g+)——快速找出未使用的索引
SELECT table_name, index_name, used FROM v$object_usage WHERE used = 'NO' -- 查看未使用的索引 ORDER BY table_name;
10. 自动生成创建缺失索引的SQL脚本
SELECT 'CREATE INDEX idx_' || table_name || '_' || column_name ||
' ON ' || table_name || '(' || column_name || ');' as create_index_sql
FROM (
SELECT DISTINCT
t.table_name,
tc.column_name
FROM user_tables t
JOIN user_tab_columns tc ON t.table_name = tc.table_name
WHERE NOT EXISTS (
SELECT 1
FROM user_ind_columns ic
WHERE ic.table_name = t.table_name
AND ic.column_name = tc.column_name
)
AND t.table_name NOT LIKE 'BIN$%'
AND tc.column_name NOT LIKE '%ID' -- 排除ID列
AND tc.data_type IN ('VARCHAR2', 'CHAR', 'NUMBER', 'DATE') -- 只对某些数据类型创建索引
)
WHERE ROWNUM <= 10; -- 限制生成的数量