Oracle 未使用分区表上的索引

Oracle 未使用分区表上的索引,oracle,optimization,indexing,partitioning,Oracle,Optimization,Indexing,Partitioning,我必须查询一个相当大的表(4.5亿行),该表是分区和索引的 假设此结构: 加载数量(整数) 客户识别码(int) 。。。还有一些专栏 该表是按负载数分区的,大约有3个负载进入一个分区。(因此load_num在分区中不是唯一的) 有三个索引,其中两个索引的前两列为load_num、cust_id(按该顺序) 当我发出此查询时: select * from fact where load_num = 100 and cust_id = 12345 返回需要相当长的时间,所以

我必须查询一个相当大的表(4.5亿行),该表是分区和索引的

假设此结构:

  • 加载数量(整数)
  • 客户识别码(int)
  • 。。。还有一些专栏
该表是按负载数分区的,大约有3个负载进入一个分区。(因此load_num在分区中不是唯一的)

有三个索引,其中两个索引的前两列为load_num、cust_id(按该顺序)

当我发出此查询时:

select *
from   fact
where  load_num = 100
       and cust_id = 12345
返回需要相当长的时间,所以我点击explain plan,它得到了正确的分区,但随后对其进行了完整的表扫描

为什么oracle不使用这两个索引中的一个来对分区进行ROWID扫描以获取行

客户id应该是唯一的,并且表中的统计数据是最新的。我们是10g企业

来自MS SQL,所以我还没有跟上Oracle的速度

提前感谢,

格特扬

**编辑:一些指定的DDL:

CREATE TABLE FACT
(
  LOAD_NUM NUMBER 
... columns ..
, CUSTOMER_ID VARCHAR2(20 BYTE) 
.. columns 
) 
TABLESPACE "TS_A" 
PCTFREE 0 
INITRANS 1 
STORAGE 
( 
  BUFFER_POOL DEFAULT 
) 
PARALLEL 12 
PARTITION BY LIST (LOAD_NUM) 
(
  PARTITION FACT_46 VALUES (46) TABLESPACE FACT_PART_DATA_46 
    COMPRESS  
, PARTITION FACT_52 VALUES (52) TABLESPACE FACT_PART_DATA_52 
    COMPRESS  
, PARTITION FACT_56 VALUES (56) TABLESPACE FACT_PART_DATA_56 
    COMPRESS  
  ... more partitions ...
)CREATE INDEX SOMESCHEMA.FACT_IDX2 ON SOMESCHEMA.FACT (LOAD_NUM ASC, CUSTOMER_ID ASC, OUTSTANDING_ID ASC) 
LOCAL 
(
  PARTITION FACT_DATA_46 
  LOGGING 
  TABLESPACE "FACT_DATA_46" 
  PCTFREE 10 
  INITRANS 2 
  STORAGE 
  ( 
    INITIAL 65536 
    MINEXTENTS 1 
    MAXEXTENTS 2147483645 
    BUFFER_POOL DEFAULT 
  ) 
  NOCOMPRESS 
, PARTITION FACT_DATA_52
  LOGGING 
  TABLESPACE "FACT_DATA_52" 
  PCTFREE 10 
  INITRANS 2 
  STORAGE 
  ( 
    INITIAL 65536 
    MINEXTENTS 1 
    MAXEXTENTS 2147483645 
    BUFFER_POOL DEFAULT 
  ) 
  NOCOMPRESS 
, 
... etc etc ..
)
为什么oracle不使用这两个索引中的一个来对分区进行ROWID扫描以获取行

很难说清楚为什么
Oracle
不使用索引,因为您的设置中没有任何东西可以阻止它这样做

最有可能的是,
cust\u id
分布是倾斜的,因此Oracle认为
分区扫描
更有效

请尝试显式添加提示:

SELECT  /*+ INDEX (f FACT_IDX2) */
        *
FROM    fact f
WHERE   load_num = 100
        AND cust_id = 12345
确保在计划中使用该方法,并检查该方法是否真的更快

此外,请发布此查询返回的内容:

SELECT  COUNT(*), COUNT(DECODE(cust_id, 12345, 1))
FROM    fact f
WHERE   load_num = 100
为什么oracle不使用这两个索引中的一个来对分区进行ROWID扫描以获取行

很难说清楚为什么
Oracle
不使用索引,因为您的设置中没有任何东西可以阻止它这样做

最有可能的是,
cust\u id
分布是倾斜的,因此Oracle认为
分区扫描
更有效

请尝试显式添加提示:

SELECT  /*+ INDEX (f FACT_IDX2) */
        *
FROM    fact f
WHERE   load_num = 100
        AND cust_id = 12345
确保在计划中使用该方法,并检查该方法是否真的更快

此外,请发布此查询返回的内容:

SELECT  COUNT(*), COUNT(DECODE(cust_id, 12345, 1))
FROM    fact f
WHERE   load_num = 100

索引是本地的还是全局的?你能发布精确的表和索引定义(带分区子句)吗?嗨,我在那里编辑了一些DDL。谢谢!索引是本地的还是全局的?你能发布精确的表和索引定义(带分区子句)吗?嗨,我在那里编辑了一些DDL。谢谢!通常,如果必须为索引提供提示,则意味着数据要么非常倾斜,要么统计数据不正确。看起来您已经涵盖了第一个案例,但它检查统计数据也会很有用。@Adam:the@op声称统计数据是最新的。Jst要确保:当我转到SqlDev中的datails选项卡时,它显示LAST_Analysis:03-DEC-10。从那以后就没有加载,所以我假设统计数据是最新的。(无论哪种方式,客户id的分布都不应改变)。现在检查查询提示。JIKES!很抱歉占用您的时间,原因如下:客户id是VARCHAR2(20字节)。我看到预测结果是:客户编号(cust_id)=12345。当我将查询更改为cust_id='12345'时,它将更改为范围扫描,并且返回速度非常快。没想到这张大桌子上的客户id是varchar。真的很抱歉,谢谢你的帮助!通常,如果必须为索引提供提示,则意味着数据要么非常倾斜,要么统计数据不正确。看起来您已经涵盖了第一个案例,但它检查统计数据也会很有用。@Adam:the@op声称统计数据是最新的。Jst要确保:当我转到SqlDev中的datails选项卡时,它显示LAST_Analysis:03-DEC-10。从那以后就没有加载,所以我假设统计数据是最新的。(无论哪种方式,客户id的分布都不应改变)。现在检查查询提示。JIKES!很抱歉占用您的时间,原因如下:客户id是VARCHAR2(20字节)。我看到预测结果是:客户编号(cust_id)=12345。当我将查询更改为cust_id='12345'时,它将更改为范围扫描,并且返回速度非常快。没想到这张大桌子上的客户id是varchar。真的很抱歉,谢谢你的帮助!