首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在Oracle函数中使用分区键

在Oracle函数中使用分区键
EN

Stack Overflow用户
提问于 2015-05-15 14:50:25
回答 1查看 1.4K关注 0票数 0

我们使用这个syntaxe在Oracle数据库中有一个分区表:

代码语言:javascript
复制
...
PARTITION BY RANGE(saledate)
(PARTITION sal99q1 VALUES LESS THAN (TO_DATE('01-APR-1999', 'DD-MON-YYYY')),
PARTITION sal99q2 VALUES LESS THAN (TO_DATE('01-JUL-1999', 'DD-MON-YYYY')),
...

我们通常在select语句中使用分区键,如下所示:

代码语言:javascript
复制
Select * from table where saledate >= trunc(sysdate-3) and saledate < trunc(sysdate-2)

为了使用更少的代码来获得相同的结果,我通常使用以下查询:

代码语言:javascript
复制
Select * from table where trunc(saledate) = trunc(sysdate-3)

我的问题是,通过在函数中使用分区键(在本例中为trunc() ),我们是否失去了分区性能?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-05-15 17:55:32

你误解了蟾蜍的计划(在你的回答中)。对于分别显示的两个查询:

代码语言:javascript
复制
Partition #: 2 Partitions determined by key values

代码语言:javascript
复制
Partition #: 1 Partitions accessed #1 - #17

第一个查询只访问它需要的分区,基于键值,即日期;因此,它只需要对可能包含日期的分区进行全面扫描。

第二个查询必须访问所有分区,因为您正在使用函数操作键值,这意味着您不再真正使用分区键。关键是saledate,而不是trunc(saledate)。这类似于在索引列上使用函数时发生的情况;在这种情况下不再使用索引,在这里不再使用分区键。正如你从你的问题中所怀疑的那样,是的,你确实失去了效率。

还可以看到,基数被猜测为50是因为函数调用,而不是由stats提供的4966值。

您可以在使用dbms_xplan的虚拟表中看到相同的内容;从第一个查询中可以看到:

代码语言:javascript
复制
--------------------------------------------------------------------------------------------------  
| Id  | Operation                 | Name | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |  
--------------------------------------------------------------------------------------------------  
|   0 | SELECT STATEMENT          |      |  4996 | 39968 |    14   (0)| 00:00:01 |       |       |  
|*  1 |  FILTER                   |      |       |       |            |          |       |       |  
|   2 |   PARTITION RANGE ITERATOR|      |  4996 | 39968 |    14   (0)| 00:00:01 |   KEY |   KEY |  
|*  3 |    TABLE ACCESS FULL      | T42  |  4996 | 39968 |    14   (0)| 00:00:01 |   KEY |   KEY |  
--------------------------------------------------------------------------------------------------  

Predicate Information (identified by operation id):                                                 
---------------------------------------------------                                                 

   1 - filter(TRUNC(SYSDATE@!-3)<TRUNC(SYSDATE@!-2))                                                
   3 - filter("SALEDATE">=TRUNC(SYSDATE@!-3) AND "SALEDATE"<TRUNC(SYSDATE@!-2))                     

第二个问题是:

代码语言:javascript
复制
--------------------------------------------------------------------------------------------        
| Id  | Operation           | Name | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |        
--------------------------------------------------------------------------------------------        
|   0 | SELECT STATEMENT    |      |    50 |   400 |    14   (0)| 00:00:01 |       |       |        
|   1 |  PARTITION RANGE ALL|      |    50 |   400 |    14   (0)| 00:00:01 |     1 |    17 |        
|*  2 |   TABLE ACCESS FULL | T42  |    50 |   400 |    14   (0)| 00:00:01 |     1 |    17 |        
--------------------------------------------------------------------------------------------        

Predicate Information (identified by operation id):                                                 
---------------------------------------------------                                                 

   2 - filter(TRUNC(INTERNAL_FUNCTION("SALEDATE"))=TRUNC(SYSDATE@!-3))                              

注意每个查询中的pstart/pstop值和基数。

您的第一个查询将更有效,因为它可以使用分区键来选择它进行完全扫描的分区,而第二个查询不能并且必须扫描所有分区。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30262563

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档