ITPUB:按道理应该走的局部分区索引

从400万行记录的1个分区中进行查询10行记录,为什么不走局部索引?

分区表,从400万行记录中取出10行记录,为什么没有走索引?
目前情况:
windows2003系统, 11gR1版本。
1, 设计rece为分区表,其中的gpsdate上建立了list分区, '20100501'对应的分区名是“P_20100501”,这个分区的记录约为400万行。
数据情况如下:
SQL> select count(*) from rece where device_number = 'A1111111' and gpsdate = '20100501' ;
COUNT(*)
----------
10
SQL> select count(*) from rece where gpsdate = '20100501' ;
COUNT(*)
----------
4026721
2, 在device_number 列上,建立局部索引,
create index idx_rece_device_number on rece(device_number) local ;
通过 SELECT segment_name, partition_name, tablespace_name
FROM user_segments
WHERE segment_name = 'IDX_RECE_DEVICE_NUMBER'; 可以看到,device_number 列上已经建立了分区索引了。
3, 已经在全表上、和'20100501' 分区上进行了分析,查看的情况如下:
SQL> select TABLE_NAME ,PARTITION_NAME, to_char(LAST_ANALYZED,'yyyymmdd hh24:mi:ss') ,GLOBAL_STATS, USER_STATS from user_tab_partitions where table_name = 'RECE';
TABLE_NAME PARTITION_NAME TO_CHAR(LAST_ANALYZED,'YYYYMMD GLOBAL_STATS USER_STATS
------------------------------ ------------------------------ ------------------------------ ------------ ----------
RECE P_20100501 20110601 16:01:52 YES NO
RECE P_20100502 20110530 13:18:05 YES NO
RECE P_20100503 20110530 13:18:16 YES NO
RECE P_20100504 20110530 13:18:27 YES NO
... 以下略去
上面表明:我在6月1日下午4点,对P_20100501分区进行过分析;而且之前在5月30日,对整个表进行过分析,这几天没有任何数据的改变。
4,但是,从400万行记录中查询10行记录的语句,却不走索引,不知道什么原因?
发现执行 select * from rece where device_number = 'A1111111' and gpsdate = '20100501' ;语句时,默认不走索引?只有加hint后,才走索引,搞不清楚什么原因?
不明白的原因是:gpsdate是分区的列,而 device_number 列上确实已经有了local索引,为什么 默认还不走索引呢?
具体的trace信息如下:
SQL> set autotrace traceonly;
SQL> select * from rece where device_number = 'A1111111' and gpsdate = '20100501' ;
已选择10行。
执行计划
----------------------------------------------------------
Plan hash value: 3235688001
--------------------------------------------------------------------------------
---------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time
| Pstart| Pstop |
--------------------------------------------------------------------------------
---------------------
| 0 | SELECT STATEMENT | | 13140 | 2001K| 25465 (1)| 00:05
:06 | | |
| 1 | PARTITION LIST SINGLE| | 13140 | 2001K| 25465 (1)| 00:05
:06 | KEY | KEY |
|* 2 | TABLE ACCESS FULL | RECE | 13140 | 2001K| 25465 (1)| 00:05
:06 | 1 | 1 |
--------------------------------------------------------------------------------
---------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("DEVICE_NUMBER"='A1111111')
统计信息
----------------------------------------------------------
0 recursive calls
0 db block gets
93744 consistent gets
93737 physical reads
0 redo size
2420 bytes sent via SQL*Net to client
520 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
10 rows processed
SQL> select /*+ index( receive_log, idx_rece_device_number) */ * from
rece where device_number = 'A1111111' and gpsdate = '20100501' ;
已选择10行。
执行计划
----------------------------------------------------------
Plan hash value: 2946187362
--------------------------------------------------------------------------------
----------------------------------------------------
| Id | Operation | Name | Row
s | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
--------------------------------------------------------------------------------
----------------------------------------------------
| 0 | SELECT STATEMENT | | 131
40 | 2001K| 875K (1)| 02:55:06 | | |
|* 1 | TABLE ACCESS BY GLOBAL INDEX ROWID| RECE | 131
40 | 2001K| 875K (1)| 02:55:06 | 1 | 1 |
|* 2 | INDEX RANGE SCAN | IDX_RECE_DEVICE_NUMBER | 10
66K| | 3730 (1)| 00:00:45 | | |
--------------------------------------------------------------------------------
----------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("GPSDATE"='20100501')
2 - access("DEVICE_NUMBER"='A1111111')
统计信息
----------------------------------------------------------
0 recursive calls
0 db block gets
7 consistent gets
0 physical reads
0 redo size
2420 bytes sent via SQL*Net to client
520 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
10 rows processed
在这个时候,再次执行: select * from rece where device_number = 'A1111111' and gpsdate = '20100501' ;看到的统计信息仍然是:
统计信息
----------------------------------------------------------
0 recursive calls
0 db block gets
93744 consistent gets
93737 physical reads
0 redo size
2420 bytes sent via SQL*Net to client
520 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
10 rows processed
我的参数是:
SQL> show parameter db_file_multi
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
db_file_multiblock_read_count integer 128
SQL> show parameter optimizer_index_cost_adj
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
optimizer_index_cost_adj integer 100
实在搞不清楚,万望不吝赐教。 搞得头晕啊。

我的分析这1个分区的命令为:
BEGIN
dbms_stats.gather_table_stats(ownname => 'AAAA',
tabname => 'RECE',
granularity => 'AUTO',
Partname => 'p_20100501',
method_opt => 'for all indexed columns size auto',
estimate_percent => dbms_stats.AUTO_SAMPLE_SIZE,
degree => 2);
end;
/
我6月1日下午,单独又分析了p_20100501这1个分区,因为只对这1个分区进行查询测试。
整个表的分析,5月30日已经完成了。
不知道为什么还是不走索引?加了hint后,物理读、一致读立刻减少非常多。

--------------------------------------------------------------

摘录,本人认为应该是走index的。

原文地址:https://www.cnblogs.com/tracy/p/2068433.html