Oracle 未使用分区表上的索引
我必须查询一个相当大的表(4.5亿行),该表是分区和索引的 假设此结构: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 返回需要相当长的时间,所以
- 加载数量(整数)
- 客户识别码(int)
- 。。。还有一些专栏
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。真的很抱歉,谢谢你的帮助!