解决Oracle数据库的索引失效,多次重建也没效果的问题

本文探讨了Oracle数据库中索引失效的多种原因,包括特殊符号使用、运算符、不合适的优化器选择等,并提供了相应的解决办法,如选用基于成本的优化器、重建索引和强制使用索引等。同时强调了定期更新统计信息对于索引效率的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一.索引失效的原因

1,<>
2,单独的>,<,(有时会用到,有时不会)
3,like “%_” 百分号在前.
4,表没分析.
5,单独引用复合索引里非第一位置的索引列.
6,字符型字段为数字时在where条件里不添加引号.
7,对索引列进行运算.需要建立函数索引.
8,not in ,not exist.
9,当变量采用的是times变量,而表的字段采用的是date变量时.或相反情况。
10, 索引失效。
11,基于cost成本分析(oracle因为走全表成本会更小):查询小表,或者返回值大概在10%以上
12,有时都考虑到了 但就是不走索引,drop了从建试试在
13,B-tree索引 is null不会走,is not null会走,位图索引 is null,is not null 都会走
14,联合索引 is not null 只要在建立的索引列(不分先后)都会走,
in null时 必须要和建立索引第一列一起使用,当建立索引第一位置条件是is null 时,其他建立索引的列可以是is null(但必须在所有列都满足is null的时候),或者=一个值;
当建立索引的第一位置是=一个值时,其他索引列可以是任何情况(包括is null =一个值),以上两种情况索引都会走。其他情况不会走

二、索引失效的解决办法

  1. 选用适合的Oracle优化器

Oracle的优化器共有3种:

a. RULE (基于规则) b. COST (基于成本) c. CHOOSE (选择性)。

设置缺省的优化器,可以通过对init.ora文件中OPTIMIZER_MODE参数的各种声明,如RULE,COST,CHOOSE,ALL_ROWS,FIRST_ROWS 。你当然也在SQL句级或是会话(session)级对其进行覆盖。

为了使用基于成本的优化器(CBO, Cost-Based Optimizer) , 你必须经常运行analyze 命令,以增加数据库中的对象统计信息(object statistics)的准确性。

如果数据库的优化器模式设置为选择性(CHOOSE),那么实际的优化器模式将和是否运行过analyze命令有关。如果table已经被analyze过, 优化器模式将自动成为CBO , 反之,数据库将采用RULE形式的优化器。

(分析table

analyze table 大写的表名 compute statistics; (我是只用了这一句,下面的没有使用)
(这一句可能导致锁定,解锁后再执行一下,看到已分析就成功了:报错信息:ORA-38029:object statistics are locked,
解决办法:
begin

dbms_stats.unlock_table_stats(‘USER_NAME’,‘TABLE_NAME’);

end;

注意;USER_NAME:schema

TABLE_NAME:表名
例子;
begin

dbms_stats.unlock_table_stats(‘cdbp’,‘T_HEALTH_HISTORY_INDEX’);

end;
在这里插入图片描述


analyze table T_HEALTH_HISTORY_INDEX compute statistics;

ANALYZE TABLE T_HEALTH_HISTORY_INDEX (表名) COMPUTE STATISTICS FOR ALL INDEXED COLUMNS;

analyze table T_HEALTH_HISTORY_INDEX compute statistics for table for all indexes for all indexed columns;

)【有一次索引失效之后,发现是数据统计的问题,具体的解决办法是执行以上语句】

在缺省情况下,Oracle采用CHOOSE优化器, 为了避免那些不必要的全表扫描(full table scan), 你必须尽量避免使用CHOOSE优化器,而直接采用基于规则或者基于成本的优化器。

2、‍重建索引
‍alter index 索引名 rebuild 【online】

3、强制索引

给该语句加上hint后,强制其使用’RECORD_ENTITYID’ 这个索引

sql语句变成这样

引用

select /*+ index(record,record_entityid) */ *

from RECORD

where entityId=‘24’ and entityType=‘blog’;

/*+ index(record,record_entityid) */ 中,index表示强制使用index,record是表名,record_entityid是索引名。其执行计划跟测试数据库上一致,都是使用用 ‘RECORD_ENTITYID’ 这个索引,逻辑读写同样为4。

后来经过测试,在不加hint的情况下,对该表和两个索引执行analyze 后,同样也能使用 ‘RECORD_ENTITYID’ 这个索引。但是因为该表更新颇为频繁,不知道要多久就要再分析一次

三、同样的sql如果在之前能够使用到索引,那么现在使用不到索引,以下几种主要情况:索引失效的原因

  1. 随着表的增长,where条件出来的数据太多,大于15%,使得索引失效(会导致CBO计算走索引花费大于走全表)

  2. 统计信息失效 需要重新搜集统计信息 (解决办法是二、1.选用适合的Oracle优化器)

  3. 索引本身失效 需要重建索引

引用于:
https://www.linuxidc.com/Linux/2012-11/74209.htm
https://www.cnblogs.com/cxxjohnson/p/5836203.html

### Oracle 中强制使用索引却失效的原因及解决方案 当尝试在 Oracle 数据库中强制使用特定索引而查询优化器未按预期工作时,可能涉及多个因素。以下是详细的分析和建议: #### 1. 索引可用性和状态验证 确保所要使用的索引确实存在并且处于有效状态。可以通过以下 SQL 查询来确认: ```sql SELECT INDEX_NAME, STATUS FROM USER_INDEXES WHERE TABLE_NAME = 'YOUR_TABLE'; ``` 如果索引的状态不是 `VALID` 或者不存在,则需要重建或重新创建该索引。 #### 2. 使用提示 (Hints) 有时即使有合适的索引,Oracle 的 Cost-Based Optimizer(CBO) 可能会选择其他路径。可以尝试通过显式的提示告诉 CBO 如何访问数据。例如,在 SELECT 语句中加入如下提示: ```sql /*+ INDEX(your_table your_index_name) */ ``` #### 3. 统计信息更新 CBO 做决策依赖于表和索引上的统计信息。旧的或者不准确的统计数据可能导致次优的选择。定期收集最新的统计信息有助于提高性能: ```sql BEGIN DBMS_STATS.GATHER_TABLE_STATS( ownname => user, tabname =>'YOUR_TABLE', estimate_percent=>DBMS_STATS.AUTO_SAMPLE_SIZE); END; / ``` #### 4. 参数设置调整 某些初始化参数也会影响索引的使用方式。特别是对于较老版本如 Oracle 9i ,应特别注意 `_LOG_PARALLELISM` 参数被设定为不大于 1 的值[^2]。此外,检查是否有任何影响执行计划生成的相关参数配置不当。 #### 5. 执行计划审查 利用 `EXPLAIN PLAN` 工具查看具体的执行计划,了解为什么有采用期望中的索引扫描操作。这可以帮助定位具体原因并采取相应措施加以修正。 ```sql EXPLAIN PLAN FOR SELECT /*+ INDEX(your_table your_index_name) */ * FROM YOUR_TABLE; -- 查看解释计划的结果 SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY()); ``` 以上方法能够帮助诊断并解决大多数情况下因各种原因导致无法正常应用指定索引的问题。当然,具体情况还需结合实际环境进一步排查。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值