使用范围分区选择列的最大值

时间:2012-10-11 07:18:58

标签: sql plsql database-partitioning

我有一个Table,它是在numeric(parameterinstanceid)值上进行范围分区的。我想选择同一列的max + 1值.i在parameterinstanceid上有全局非分区索引。

select /*+ parallel(a,32,8) */ max(parameterinstanceid) +1 from parameterinstance a;

在检查解释计划时,我发现它正在桌面上进行INDEX FULL SCAN(MIN / MAX)。我想通过首先检查max partition,如果它不包含任何数据,然后下一个分区,按顺序.i可以编写一个程序来执行此操作,但我想知道是否有一个简单的查询。 http://www.oramoss.com/blog/2009/06/no-pruning-for-minmax-of-partition-key.html ..似乎这是一个未解决的问题。

编辑:

分区名称为PI_P01,PI_P02,... PI_P10,PI_PMAXVALUE

解释计划是:

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 2808487136

-----------------------------------------------------------------------------------------------------
| Id  | Operation                   | Name  | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |
-----------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |       |     1 |     8 |    34   (0)| 00:00:01 |       |       |
|   1 |  SORT AGGREGATE             |       |     1 |     8 |            |          |       |       |
|   2 |   PARTITION RANGE ALL       |       |     1 |     8 |    34   (0)| 00:00:01 |     1 |    11 |
|   3 |    INDEX FULL SCAN (MIN/MAX)| PI_PK |     1 |     8 |    34   (0)| 00:00:01 |     1 |    11 |
-----------------------------------------------------------------------------------------------------

和表格结构:

 Name                           Null?    Type
 ------------------------------ -------- -----------------
 PARAMETERINSTANCEID            NOT NULL NUMBER
 PARAMINSTANCE2PARAMSETVERSION  NOT NULL NUMBER
 PARAMINSTANCE2PARAMDEFINITION  NOT NULL NUMBER
 PARAMINSTANCE2PARENTPARAM               NUMBER
 SEQUENCE                                NUMBER
 X_CTCV_CONV_ID                          VARCHAR2(50 CHAR)
 X_CONV_RUN_NO                           NUMBER

和表格上的索引:

    INDEX_NAME                     POSITION COLUMN_NAME 
------------------------------ -------- -----------------------------
PI_UK                                 1 PARAMINSTANCE2PARAMSETVERSION
PI_UK                                 2 PARAMINSTANCE2PARAMDEFINITION
PI_PK                                 1 PARAMETERINSTANCEID            
PI_PAD_FK_I                           1 PARAMINSTANCE2PARAMDEFINITION
PI_PI_FK_I                            1 PARAMINSTANCE2PARENTPARAM      

1 个答案:

答案 0 :(得分:1)

如果分区键上有全局索引,则应该得到如下计划:

----------------------------------------------------------------------------
| Id  | Operation                  | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------
|   0 | SELECT STATEMENT           |     1 |     9 |     2   (0)| 00:00:01 |
|   1 |  SORT AGGREGATE            |     1 |     9 |            |          |
|   2 |   INDEX FULL SCAN (MIN/MAX)|     1 |     9 |     2   (0)| 00:00:01 |
----------------------------------------------------------------------------

这里MIN/MAX非常重要,这意味着Oracle将stop at the first entry绕过分区表。

您提供的链接不同,因为分区键未编入索引(因此它会生成FULL TABLE SCAN而不是INDEX FULL SCAN

如果分区键上没有索引,那么按照Jonathan Lewis的建议进行TOP-N查询似乎可以完全按照您的意愿行事。以下是我在表test中获得的计划,如链接中的示例所示:

explain plan for 
select * from (select col_date_part_key 
                 from test 
                order by col_date_part_key desc) 
 where rownum = 1

-------------------------------------------------------------------------
| Id  | Operation                | Name | Rows  | Bytes | Pstart| Pstop |
-------------------------------------------------------------------------
|   0 | SELECT STATEMENT         |      |     1 |     9 |       |       |
|*  1 |  COUNT STOPKEY           |      |       |       |       |       |
|   2 |   PARTITION RANGE ALL    |      |     1 |     9 |    12 |     1 |
|   3 |    VIEW                  |      |     1 |     9 |       |       |
|*  4 |     SORT ORDER BY STOPKEY|      |     1 |     9 |       |       |
|   5 |      TABLE ACCESS FULL   | TEST |     1 |     9 |    12 |     1 |
-------------------------------------------------------------------------

正如您所看到的,Oracle将从最后一个分区(Pstart=12)开始,并将走到第一个分区(Pstart=1),直到它获得一行(Rows=1)。 / p>


更新

我已经运行了另一个测试,希望与您的设置类似,我找到了一个不同的,更合乎逻辑的计划。设置:

create table parameterinstance  (
   PARAMETERINSTANCEID           NUMBER             NOT NULL,
   PARAMINSTANCE2PARAMSETVERSION NUMBER             NOT NULL,
   PARAMINSTANCE2PARAMDEFINITION NUMBER             NOT NULL,
   PARAMINSTANCE2PARENTPARAM     NUMBER                     ,
   SEQUENCE                      NUMBER                     ,
   X_CTCV_CONV_ID                VARCHAR2(50 CHAR)          ,
   X_CONV_RUN_NO                 NUMBER                     
) partition by range (PARAMETERINSTANCEID)
(  partition p1 values less than (1000) storage (initial 64k),
   partition p2 values less than (2000) storage (initial 64k),
   partition p3 values less than (3000) storage (initial 64k),
   partition p4 values less than (4000) storage (initial 64k),
   partition p5 values less than (5000) storage (initial 64k),
   partition p6 values less than (6000) storage (initial 64k),
   partition p7 values less than (7000) storage (initial 64k),
   partition p8 values less than (8000) storage (initial 64k),
   partition p9 values less than (9000) storage (initial 64k),
   partition p10 values less than (maxvalue) storage (initial 64k)
);

CREATE UNIQUE INDEX PI_PK ON parameterinstance(PARAMETERINSTANCEID) local;

insert into parameterinstance  
  (SELECT rownum, rownum, rownum, '', '', rpad('x', 50, 'x'), '' 
     from dual connect by level <= 1e4);

11gR2 上,我得到以下计划:

-----------------------------------------------------------------------------
| Id  | Operation                   | Name  | Rows  | Bytes | Pstart| Pstop |
-----------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |       |     1 |    13 |       |       |
|   1 |  PARTITION RANGE ALL        |       |     1 |    13 |    10 |     1 |
|   2 |   SORT AGGREGATE            |       |     1 |    13 |       |       |
|   3 |    INDEX FULL SCAN (MIN/MAX)| PI_PK |     1 |    13 |    10 |     1 |
-----------------------------------------------------------------------------

请注意,分区以适当的顺序列出(从10向下到1)。该计划在 9iR2

中有所不同
-----------------------------------------------------------------------------
| Id  | Operation                   | Name  | Rows  | Bytes | Pstart| Pstop |
-----------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |       |     1 |     4 |       |       |
|   1 |  SORT AGGREGATE             |       |     1 |     4 |       |       |
|   2 |   PARTITION RANGE ALL       |       |       |       |     1 |    10 |
|   3 |    INDEX FULL SCAN (MIN/MAX)| PI_PK | 10000 | 40000 |     1 |    10 |
-----------------------------------------------------------------------------

所以似乎在9i和11g之间发生了一些优化。是时候升级了吗?