Oracle数据库索引查询方式

 更新时间:2026年01月06日 08:59:55   作者:dazhong2012  
文章介绍了索引的类型、适用场景、优缺点,以及索引查询方法和优化策略,还提供了一个查询实践案例,帮助读者更好地理解和应用索引优化

一、索引基础概念

​​索引类型与适用场景​​

  • ​​B树索引​​:最常用,适合高基数列(唯一值多)的等值或范围查询。

  • ​​位图索引​​:适用于低基数列(如性别、状态),常用于数据仓库。

  • ​​函数索引​​:基于列的函数表达式创建(如UPPER(name)),优化带函数的查询。

  • ​​复合索引​​:多列组合,列顺序至关重要(高选择性列在前)。

  • ​​反向索引​​:优化模糊查询(如LIKE ‘%abc’)。

​​ 索引的优缺点​​

  • 优点​​:加速数据检索,减少磁盘I/O。
  • 缺点​​:占用存储空间;降低DML操作(增删改)效率;需定期维护。

二、索引查询方法

1. ​​查看索引元信息​​

​​表的所有索引​​

SELECT index_name, index_type, uniqueness 
FROM dba_indexes 
WHERE table_name = 'EMPLOYEES';

​​索引的列信息​​

SELECT column_name, column_position 
FROM dba_ind_columns 
WHERE index_name = 'IDX_DEPT_FIRSTNAME';

索引所在的表信息分析

SELECT i.index_name, i.table_name, ic.column_name, ic.column_position
FROM dba_indexes i
JOIN dba_ind_columns ic ON i.index_name = ic.index_name
WHERE i.index_name = 'IDX_NAME'; --按索引名称条件查询

2. ​​分析索引使用情况​​

​​监控索引使用频率​​

SELECT * FROM v$index_usage;  -- 跟踪索引是否被有效利用,需 12c 以上版本管理员权限

​​检查未使用索引​​

SELECT index_name FROM dba_indexes 
WHERE index_name NOT IN (SELECT name FROM v$index_usage);

索引碎片与空间效率

-- 1.查询当前用户创建的索引碎片率
SELECT index_name,
       blevel,
       leaf_blocks,
       clustering_factor,
       ROUND((leaf_blocks * 100) / NULLIF(clustering_factor, 0), 2) AS fragmentation_ratio
FROM (
    SELECT di.index_name,
           di.blevel,
           di.leaf_blocks,
           di.clustering_factor
    FROM dba_indexes di
    JOIN dba_tables dt ON di.table_name = dt.table_name
    WHERE dt.owner = USER -- 只查询当前用户创建的表
      AND di.clustering_factor > 1
) t
WHERE (leaf_blocks * 100) / clustering_factor > 30; -- >30%表示需重建

-- 2.查询 索引所在的表信息分析
SELECT i.index_name, i.table_name, ic.column_name, ic.column_position
FROM dba_indexes i
JOIN dba_ind_columns ic ON i.index_name = ic.index_name
WHERE i.index_name = 'IDX_NAME'; --按索引名称条件查询

--3.重建碎片化索引​​
ALTER INDEX IDX_NAME REBUILD ONLINE;  -- IDX_NAME  为索引名称

3. ​​执行计划分析​​

EXPLAIN PLAN FOR 
SELECT * FROM employees WHERE department_id = 10;
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);

关键指标​​:

  • INDEX RANGE SCAN:索引有效使用。
  • FULL TABLE SCAN:可能缺失或未使用索引。

三、优化索引空间的策略​

1. 创建索引

CREATE UNIQUE INDEX idx_user_name ON user_info(user_name) 
TABLESPACE idx_tbs 
COMPRESS NOLOGGING;

2. 重建碎片化索引​​

ALTER INDEX IDX_OLD REBUILD ONLINE;  -- 减少空间碎片,提升查询效率

3. ​​调整存储参数​​

ALTER INDEX IDX_LARGE PCTFREE 10;  -- 降低空闲空间预留,压缩索引体积

4. 删除冗余索引​​

DROP INDEX IDX_REDUNDANT;  -- 通过监控确认使用率低的索引

5. ​​启用高级压缩​​(仅限企业版)

ALTER INDEX IDX_BIG COMPRESS ADVANCED LOW;  -- 节省30-50%空间

四、关键监控指标​​

​​指标​​ ​​查看方式​​ ​​优化阈值​​
​​索引大小​​dba_segments.bytes>表空间的20%需优化
​​碎片率​​(leaf_blocks / clustering_factor) * 100>30%需重建
​​使用频率​​v$index_usage.user_reads近30天无读操作可删
​​分区均匀性​​dba_index_partitions.bytes 的方差值方差>50%需调整分区

五、 查询实践案例

1. ​​查询 Oracle 表空间大小

-- 表空间使用率监控(含自动扩展状态)
SELECT 
    df.tablespace_name "Tablespace",
    df.total_mb,
    df.total_mb - fs.free_mb "Used_MB",
    fs.free_mb "Free_MB",
    ROUND((df.total_mb - fs.free_mb) / df.total_mb * 100, 2) Pct_Used, -- 使用率
    autoext "AutoExt"
FROM 
    (SELECT tablespace_name, 
            SUM(bytes)/1024/1024 total_mb,
            MAX(DECODE(autoextensible,'YES','Y','N')) autoext
     FROM dba_data_files 
     GROUP BY tablespace_name) df
JOIN 
    (SELECT tablespace_name, 
            SUM(bytes)/1024/1024 free_mb 
     FROM dba_free_space 
     GROUP BY tablespace_name) fs 
    ON df.tablespace_name = fs.tablespace_name
WHERE ROUND((df.total_mb - fs.free_mb) / df.total_mb * 100, 2) > 80  -- 仅显示>80%使用率的表空间
ORDER BY Pct_Used DESC;

结果示例:

Tablespacetotal_mbUsed_MBFree_MBPct_UsedAutoExt
TBS_PICP3548330923993.26
TBS_PICP_NEW4048352352587.03

2. 查询 Oracle 索引使用情况

替换 PICP_FORMAL(表用户) 和 T_USER_INFO(表名称 需大写)

-- 替换 PICP_FORMAL 和 T_USER_INFO(需大写)
WITH table_info AS (
    SELECT 
        t.owner,
        t.table_name,
        t.tablespace_name,
        t.num_rows,
        t.avg_row_len,
        ROUND((t.num_rows * t.avg_row_len) / 1024 / 1024, 2) AS estimated_data_size_mb,
        ROUND(SUM(s.bytes) / 1024 / 1024, 2) AS actual_table_size_mb
    FROM dba_tables t
    JOIN dba_segments s ON t.owner = s.owner AND t.table_name = s.segment_name
    WHERE t.owner = 'PICP_FORMAL'
      AND t.table_name = 'T_USER_INFO'
      AND s.segment_type = 'TABLE'
    GROUP BY t.owner, t.table_name, t.tablespace_name, t.num_rows, t.avg_row_len
),
index_info AS (
    SELECT 
        i.index_name,
        ROUND(s.bytes / 1024 / 1024, 2) AS index_size_mb,
        i.uniqueness
    FROM dba_indexes i
    JOIN dba_segments s ON i.owner = s.owner AND i.index_name = s.segment_name
    WHERE i.table_owner = 'PICP_FORMAL'
      AND i.table_name = 'T_USER_INFO'
      AND s.segment_type = 'INDEX'
)
SELECT 
    -- 表基本信息
    ti.table_name,
    ti.tablespace_name,
    ti.num_rows,
    ti.avg_row_len,
    ti.estimated_data_size_mb,
    ti.actual_table_size_mb,
    
    -- 索引详细信息
    ii.index_name,
    ii.index_size_mb,
    ii.uniqueness,
    
    -- 索引汇总信息
    ROUND(SUM(ii.index_size_mb) OVER (), 2) AS total_index_size_mb,
    ROUND((SUM(ii.index_size_mb) OVER () / ti.actual_table_size_mb) * 100, 2) AS index_to_table_ratio_percent
FROM table_info ti
LEFT JOIN index_info ii ON 1=1
ORDER BY ii.index_size_mb DESC NULLS LAST;

示例结果如下:

TABLE_NAMETABLESPACE_NAMENUM_ROWSAVG_ROW_LENESTIMATED_DATA_SIZE_MBACTUAL_TABLE_SIZE_MBINDEX_NAMEINDEX_SIZE_MBUNIQUENESSTOTAL_INDEX_SIZE_MBINDEX_TO_TABLE_RATIO_PERCENT
T_USER_INFOTBS_PICP_NEW63604637262.55271PK_T_USER_ID45UNIQUE37137.09
T_USER_INFOTBS_PICP_NEW63604637262.55271IDX_USER_NAME28NONUNIQUE7137.09

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • oracle数据库添加或删除一列的sql语句

    oracle数据库添加或删除一列的sql语句

    需要注意的一点,如果要修改的表,不是当前的用户的表,那么就需要添加上用户的名称。以及有修改此表的权限
    2012-05-05
  • [Oracle] 常用工具集之SQL*Loader的用法

    [Oracle] 常用工具集之SQL*Loader的用法

    SQL*Loader是Oracle提供的用于数据加载的一种工具,它比较适合业务分析类型数据库(数据仓库),能处理多种格式的平面文件,批量数据装载比传统的数据插入效率更高
    2013-07-07
  • 如何保持Oracle数据库的优良性能

    如何保持Oracle数据库的优良性能

    如何保持Oracle数据库的优良性能...
    2007-03-03
  • Excel导入oracle的几种方法

    Excel导入oracle的几种方法

    本篇文章是对Excel导入oracle的几种方法进行了详细的分析介绍,需要的朋友参考下
    2013-06-06
  • MSSQL与Oracle数据库事务隔离级别与锁机制对比

    MSSQL与Oracle数据库事务隔离级别与锁机制对比

    事务隔离级别是并发控制的整体解决方案,其实际上是综合利用各种类型的锁和行版本控制,来解决并发问题。锁是数据库并发控制的内部机制,是基础。对用户来说,只有当事务隔离级别无法解决一些并发问题和需求时,才有必要在语句中手动设置锁。
    2014-08-08
  • Oracle数据库rownum和row_number的不同点

    Oracle数据库rownum和row_number的不同点

    在Oracle中,有一个很有趣的东西,那就是rownum。当你从某个表中查询数据的时候,返回的结果集中都会带有rownum这个字段,而且有时候也可以使用rownum进行一些条件查询
    2015-11-11
  • navicat使用Oracle创建库以及用户超详细教程

    navicat使用Oracle创建库以及用户超详细教程

    本文介绍如何使用Navicat连接Oracle数据库,步骤包括准备工作、新建连接、输入用户名和密码、测试连接、建立库和用户、授权以及测试的相关资料,需要的朋友可以参考下
    2024-09-09
  • oracle分页存储过程 oracle存储过程实例

    oracle分页存储过程 oracle存储过程实例

    这篇文章主要介绍了oracle存储过程实例,实现oracle查询数据分页,大家参考使用吧
    2014-01-01
  • ORACLE 回收站当前状态查询整理

    ORACLE 回收站当前状态查询整理

    回收站(Recycle Bin)从原理上来说就是一个数据字典表,放置用户删除(drop)掉的数据库对象信息,接下来详细介绍下ORACLE 回收站方方面面感兴趣的你可以参考下哈
    2013-03-03
  • Oracle创建主键自增表(sql语句实现)及触发器应用

    Oracle创建主键自增表(sql语句实现)及触发器应用

    主键自增在插入数据的时候是很实用的,可以获取并操作返回的插入记录的ID,接下来介绍Oracle如何创建主键自增表,感兴趣的你可以了解下,就当是巩固知识,希望此文对你有所帮助
    2013-01-01

最新评论