在Oracle上强制进行分区修剪

时间:2017-05-31 12:28:47

标签: oracle performance optimization partitioning oracle12c

我有一个与此类似的查询

select *
from small_table A
inner join huge_table B on A.DATE =B.DATE

huge_table由DATE分区,PK为DATE,some_id和some_other_id(因此连接不是由pk索引完成的)。 small_table只包含几个日期。

SQL的总成本为48分钟

由于某种原因,解释计划给了我一个" PARTITION RANGE(ALL)"在基数上有很高的数字。看起来像是访问整个表,而不仅仅是访问small_table.DATE

指示的分区

如果我将SQL放在循环中并执行

for o in (select date from small_table)
loop
    select *
    from small_table A
    inner join huge_table B on A.DATE =B.DATE
    where B.DATE=O.DATE
end loop;

仅需2分40秒(完整循环)。 有什么方法可以在Oracle 12c上强制进行分区修剪?

其他信息:

small_table有13个不同日期的37条记录。 huge_table拥有8,000,000条记录,包含179个日期/分区。 SQL需要small_table中的一个字段,但我可以调整SQL以不使用它

更新

使用use_nl hint,现在执行计划中的基数显示更准确,执行时间从48分钟缩短到4分钟。

select /* use_nl(B) */*
from small_table A
inner join huge_table B on A.DATE =B.DATE

1 个答案:

答案 0 :(得分:3)

这似乎是问题所在:

  

small_table有13个不同日期的37个注册管理机构。huge_table拥有8.000万个注册管理机构,有179个日期/分区....   SQL需要small_table中的一个字段,但我可以调整SQL以不使用它“

根据您发布的SQL,您只在DATE列中加入了两个表,没有其他条件。如果确实如此,那么您正在生成一个交叉连接,其中huge_table的每个分区都加入small_table 2-3次。因此,您的结果集可能比您预期的要大得多,这意味着更多的数据库工作量,这意味着更多的时间。

要注意的另一件事是small_tablehuge_table分区的基数大约是1:4;优化器不知道实际上只有十三个不同的huge_table分区在起作用。

优化应该是一门科学,除了尝试这一点之外,这比其他任何事情更多猜测:

select B.*
from ( select /*+ cardinality(t 13) */
             distinct t.date
        from small_table t ) A
inner join huge_table B 
    on A.DATE =B.DATE

这应该与优化器通信,只需要一小部分huge_table分区,这可能会使它选择分区修剪。它也删除了笛卡尔积,这也应该提高性能。显然,您需要应用您提到的调整,以便无需查询small_table中的任何其他内容。