游乐游手机版
首页/数据库/文章详情

Oracle查询所有表索引个数的详细方法和SQL示例代码

时间:2026-06-12 07:08
汇总了10个Oracle索引查询脚本,涵盖表索引数量统计、无索引表发现、大表监控、索引使用分析等场景。每个脚本附详细注释,可直接复制用于日常数据库运维与性能调优,提升索引管理效率。

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

1. 查询当前用户下所有表的索引数量统计

oracle查所有表的索引个数的示例代码

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;  -- 限制生成的数量
来源:https://www.jb51.net/database/357864wcw.htm
上一篇SQL Server如何将两张表合并成一张表的详细方法教程 下一篇Oracle连接类型详解与性能对比分析
本站内容用于信息整理与展示,如有侵权或内容问题请及时联系处理。

相关推荐

补充同频道和同主题内容,方便继续浏览更多相关内容。

同类最新

继续查看同栏目最近更新的文章。

更多
Redis 7.0增量AOF重写RDB前导码配置详解
数据库 · 2026-07-02

Redis 7.0增量AOF重写RDB前导码配置详解

先说一个几乎所有人都踩过的典型误区:很多人把 aof-use-rdb-preamble yes 当作开启“增量重写”的开关。实际上,这个配置只干了一件事——让重写后的 AOF 文件头部带上 RDB 快照。它解决的是加载速度问题,跟“增量重写”本身的概念压根不是一回事。真正的增量重写,依赖的是 Red

在Python Tornado异步框架中安全执行SQL命令的方法与最佳实践
数据库 · 2026-07-02

在Python Tornado异步框架中安全执行SQL命令的方法与最佳实践

直接在Tornado里用SQLAlchemy同步执行SQL,结果就是阻塞IOLoop,所谓“异步框架里写同步数据库代码”,等于白搭。安全执行的关键不是“怎么写SQL”,而是“怎么不卡住事件循环”。 为什么不能在RequestHandler里直接调用session execute() 因为sessio

利用SQL触发器实现在INSERT数据时自动同步到审计表
数据库 · 2026-07-02

利用SQL触发器实现在INSERT数据时自动同步到审计表

先说结论:可以用触发器把 INSERT 数据同步到审计表,但必须用 AFTER INSERT,并且审计表的字段顺序、类型、字符集得和源表严格一致。否则,轻则写入错位、数据截断,重则直接报错、丢数据。下面把这些坑一个一个掰开说。 能,但必须用 AFTER INSERT,且审计表字段顺序、类型、字符集要

如何用SQL编写按不同工作日统计员工出勤率
数据库 · 2026-07-02

如何用SQL编写按不同工作日统计员工出勤率

在实际业务中,统计不同工作日的出勤率是HR系统里的高频需求。如果直接按日期函数分组,很容易掉进语言环境、索引失效或分母口径的坑里。下面就来拆解具体的实现要点。 必须用 CASE WHEN 将日期映射为固定 weekday 标签(如 Mon )再分组,避免语言环境导致的分组断裂;需过滤 DOW IN

Spring Boot 3动态拼接SQL为何引发严重安全漏洞
数据库 · 2026-07-02

Spring Boot 3动态拼接SQL为何引发严重安全漏洞

SQL注入漏洞的核心成因,本质上是因为用户输入直接参与了SQL语句的字符串拼接,而未采用参数化绑定机制。在MyBatis中使用${}、QueryWrapper中调用apply()与last()、JPA的@Query注解进行拼接等操作,都会绕过PreparedStatement的安全防护。动态字段必须