0

我有一个按数字(参数实例ID)值划分范围的表。我想选择同一列的 max+1 值。我在 parameterinstanceid 上有全局非分区索引。

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

在检查解释计划时,我看到它正在桌子上进行 INDEX FULL SCAN (MIN/MAX)。我想通过首先检查最大分区来做到这一点,如果它不包含任何数据,然后是下一个分区,按 desc 顺序。我可以编写一个过程来做到这一点,但我想知道是否有一个简单的查询。 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      
4

1 回答 1

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会在第一个条目处停止,绕过分区表。

您提供的链接不同,因为分区键没有被索引(因此它产生 aFULL 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)。


更新

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

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 之间发生了一些优化。是时候升级了?

于 2012-10-11T12:43:57.250 回答