未使用范围间隔分区 table 中的本地索引

Local index in Range interval partitioned table is not being used

我有一个分区的范围区间 table。它有 6 万亿数据 1 年。

    CREATE TABLE eip.Meter_Read_Alert_test
     (
       Mfg_serial_num  VARCHAR2(50 BYTE) ,
       Channel_id  NUMBER NOT NULL,
       Read_time TIMESTAMP(0),
       CONSTRAINT pk_Alert_test PRIMARY KEY (ID,channel_id,Read_time)
     )
     PARTITION BY RANGE (Read_time) INTERVAL(NUMTOYMINTERVAL(1, 'MONTH'))
     (  
       PARTITION p1 VALUES less than('01-09-19 12:00:00.000000000 AM')
     ) ;

在以下列上创建本地索引:

CREATE INDEX mfg_SNo_test_idx on eip.Meter_Read_Alert_test ( Mfg_serial_num ) tablespace SPRING_METER_READ Local ;
CREATE INDEX channel_ID_test_idx on eip.Meter_Read_Alert_test (Channel_ID) tablespace SPRING_METER_READ   Local ;
CREATE INDEX ReadTime_test_idx on eip.Meter_Read_Alert_test (Read_Time) tablespace SPRING_METER_READ   Local ;

问题: 当我 运行 下面的查询时, ReadTime_test_idx 索引没有被使用。正在全面 table 扫描。

select * from meter_read_alert_test 
where  read_time between '19-11-2019 12:00:00 AM' and '19-11-2019 11:00:00 PM';

    Plan hash value: 2722527583

-----------------------------------------------------------------------------------------------------------------
| Id  | Operation                | Name                 | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |
-----------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT         |                      |  9090K|   728M|   411K  (6)| 00:00:17 |       |       |
|   1 |  PARTITION RANGE ITERATOR|                      |  9090K|   728M|   411K  (6)| 00:00:17 |   KEY |   KEY |
|*  2 |   TABLE ACCESS FULL      | METER_READ_ALERT_TEST |  9090K|   728M|   411K  (6)| 00:00:17 |   KEY |   KEY |
-----------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - filter("READ_TIME">=TO_TIMESTAMP('19-11-2019 12:00:00 AM') AND 
              "READ_TIME"<=TO_TIMESTAMP('19-11-2019 11:00:00 PM'))

请指出这里出了什么问题以及如何解决。

Oracle 使用完整 table 扫描而不是索引范围扫描不一定会做错任何事情。全 table 扫描在读取大量数据时最好,因为全 table 扫描可以使用多块读取,而不必为每个值遍历树结构,并且如果索引数据是无序的,索引读取可能必须从 table 中检索所有块。

虽然您的查询只读取了全部数据的一小部分,但它从分区中读取了 "large" 百分比的数据。由于 table 是按月分区的,Oracle 正在使用分区修剪来立即消除大部分数据(您可以在 "Key" 启动和停止分区中看到这一点)。在该分区内,查询正在读取大约一天的数据量,这大约是分区中数据的 3%。没有代表 "large" 百分比的通用数字,但在许多情况下,3% 的完整 table 扫描比索引更好。

这里有可能是 Oracle 猜错了。您可能想尝试使用 select /*+ index(meter_read_alert_test) */ ... 等索引提示进行查询。如果这提高了性能,请首先尝试重新收集统计信息。您通常不需要使用索引提示。