让 Oracle 优化器使用虚拟列来查找分区

Sea*_*yen 6 oracle partitioning

我有一个包含三列的大表,如下所示:

"START_DATE" DATE,
"START_VALUE" NUMBER(10,7)
"START_DATE_VALUE" NUMBER(18,7) 
  GENERATED ALWAYS AS 
  (
    (extract(YEAR FROM START_DATE) * 10000 + 
     extract(MONTH FROM START_DATE)*100 + 
     extract(DAY FROM START_DATE))*power(10,3) + 
     (START_VALUE+180)
  ) VIRTUAL
Run Code Online (Sandbox Code Playgroud)

START_DATE_VALUE列是用于分区的虚拟列。但是,当我有这样的查询时:

select * 
from mytable
where
      start_date > to_date('02-01-2012', 'MM-DD-YYYY')
 and start_value > 120.23452
Run Code Online (Sandbox Code Playgroud)

它扫描所有分区以获取结果。如何让 Oracle 使用虚拟列,然后选择正确的分区来处理它?

抱歉,我的表定义非常大,我无法将其复制到此处。

mir*_*173 2

我认为您的虚拟列定义有问题。对于特殊值2012-02-01(采用YYYY-MM-DD格式)和120.23452,虚拟列的值为

2012*10000+2*100+1*1000+180+120.23452 = 20120000+200+1000+300.23452 =20121500.23452
Run Code Online (Sandbox Code Playgroud)

并不是

20120201300.23452
Run Code Online (Sandbox Code Playgroud)

正如你所期望的。

另请检查您的虚拟列是否是表分区所依据的列。

来自VLDB 和分区指南

基于虚拟列的分区表受益于在 SQL 语句中使用虚拟列定义表达式的语句的分区修剪。

所以我认为select语句

select * from mytable where start_date > todate('02-01-2012', 'MM-DD-YYYY') and    start_value > 120.23452
Run Code Online (Sandbox Code Playgroud)

应该是这样的

select * from mytable where (
  extract(YEAR FROM START_DATE) * 10000 + 
  extract(MONTH FROM START_DATE)*100 + 
  extract(DAY FROM START_DATE))*power(10,3) + 
  (START_VALUE+180)
)  > 20121500.23452
Run Code Online (Sandbox Code Playgroud)

进行分区修剪。

todate
Run Code Online (Sandbox Code Playgroud)

您在select语句中使用的函数在 oracle sql 中不存在。函数的名称是

to_date
Run Code Online (Sandbox Code Playgroud)

.