未使用分区表上的索引

发布于 2024-10-11 07:19:44 字数 1703 浏览 6 评论 0原文

我必须查询一个相当大的表(450M 行),该表已分区并建立了索引。

假设以下结构:

  • load_num(int)
  • cust_id(int)
  • ... 更多列 ...

该表通过 load_num 进行分区,大约 3 个负载进入一个分区。 (因此 load_num 在分区内不是唯一的)

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

当我发出此查询时:

select *
from   fact
where  load_num = 100
       and cust_id = 12345

返回需要很长时间,所以我打解释计划,它获得正确的分区,然后对其进行全表扫描。

为什么 Oracle 不使用两个索引之一对分区进行 ROWID 扫描来获取行?

cust_id 应该相当唯一,并且表上的统计信息是最新的。我们使用 10g Enterprise。

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

提前致谢,

Gert-Jan

** 编辑:一些匿名 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 ..
)

I have to query a reasonably large table (450M rows) that is partitoned and indexed.

suppose this structure:

  • load_num(int)
  • cust_id(int)
  • ... some more columns ...

The table is partitioned over load_num, around 3 loads go into one partition. (so load_num is not unique within a partition)

There there are three indexes, two of them who have load_num, cust_id as the first two columns (int that order)

When I issue this query:

select *
from   fact
where  load_num = 100
       and cust_id = 12345

It takes quite long to return, so I hit explain plan and it gets the right partition but then does a FULL table scan on it.

Why isn't oracle using one of the two indexes to do a ROWID scan on the partition to get the rows?

The cust_id should be fairly unique and the statistics on the table are up to date. We're on 10g Entreprise.

Came from MS SQL so I'm not up to speed with Oracle yet.

Thanks in advance,

Gert-Jan

** EDIT: Some anonimized 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 ..
)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

我最亲爱的 2024-10-18 07:19:44

为什么 Oracle 不使用两个索引之一对分区进行 ROWID 扫描来获取行?

很难确切地说明为什么 Oracle 不使用索引,因为您的设置中没有任何内容可以阻止它这样做。

最有可能的是,cust_id 分布是倾斜的,因此 Oracle 认为 PARTITION SCAN 更有效。

您能否尝试明确添加提示:

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

Why isn't oracle using one of the two indexes to do a ROWID scan on the partition to get the rows?

It's hard to tell exactly why Oracle doesn't use the index, since there is nothing in your setup that would prevent it from doing so.

Most probably, cust_id distribution is skewed so that Oracle considers PARTITION SCAN more efficient.

Could you please try adding the hint explicitly:

SELECT  /*+ INDEX (f FACT_IDX2) */
        *
FROM    fact f
WHERE   load_num = 100
        AND cust_id = 12345

Make sure that it's used in the plan and check that this method is really faster.

Also, please post what does this query return:

SELECT  COUNT(*), COUNT(DECODE(cust_id, 12345, 1))
FROM    fact f
WHERE   load_num = 100
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文