2017-05-12 56 views
0

我在优化语句时遇到问题。对应的表(INTERVAL_TBL)包含大约11.000.000行,这使得我的测试系统中这条语句花费了大约8秒。即使在专用的Oracle服务器上(24GB内存,17GB数据库大小),也需要大约4-5秒的时间。Oracle TOP优化

SELECT 
ID, STATUS_ID, INTERVAL_ID, BEGIN_TS, END_TS, PT, DISPLAYTEXT, RSC 
FROM 
(
SELECT 
    INTERVAL_TBL.ID, INTERVAL_TBL.INTERVAL_ID, INTERVAL_TBL.STATUS_ID, INTERVAL_TBL.BEGIN_TS, INTERVAL_TBL.END_TS, INTERVAL_TBL.PT, ST_TBL.DISPLAYTEXT, ST_TBL.RSC, 
    RANK() OVER (ORDER BY BEGIN_TS DESC) MY_RANK 
FROM INTERVAL_TBL 
INNER JOIN ST_TBL ON ST_TBL.STATUS_ID = INTERVAL_TBL.STATUS_ID 
WHERE ID = '<id>' 
) 
WHERE MY_RANK <= 10 

所有我想知道是否有优化的声明(选择由BEGIN有序最近行)的方式首先。

其次,我想知道是否有人可以根据声明为索引提出建议。

编辑:

解释计划:


PLAN_TABLE_OUTPUT 
-------------------------------------------------------------------------------- 

| Id | Operation   | Name    | Rows | Bytes | Cost (%CPU)| Time  | 
| 0 | SELECT STATEMENT |     | 525K| 79M| 58469 (1)| 00:00:03 | 
|* 1 | HASH JOIN   |     | 525K| 79M| 58469 (1)| 00:00:03 | 
| 2 | TABLE ACCESS FULL| ST_TBL   | 46 | 2438 |  3 (0)| 00:00:01 | 
|* 3 | TABLE ACCESS FULL| INTERVAL_TBL  | 525K| 52M| 58464 (1)| 00:00:03 | 


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

    1 - access("ST_TBL"."STATUS_ID"="INTERVAL_TBL"."STATUS_ID") 
    3 - filter("INTERVAL_TBL"."ID"='aef830a6-275b-4713-90da-9135f3f91a32'") 
  • 行中INTERVAL_TBL:10.673.122
  • 行中ST_TBL:46个
  • 行中接合子集:10.673。 122
  • 连接子集中的行与f ILTER对ID:530.073

理想的情况下它会得到下降到约几毫秒。那就是那个语句在MS SQL Server中有10.000.000行的含义。

+1

调整是所有关于细节。每个表中有多少行?加入的结果集中有多少(是1100万)?有多少按“ID”过滤(以及属于哪个表)?另外,在没有看到解释计划的情况下,很难对查询性能进行具体的观察。时间到了哪里? – APC

+0

说实话,4-5秒对于排序1100万行并不是太破旧。你想什么时候把它放下? – APC

+0

您是否尝试使用“仅提取前10行”而不是窗口函数? –

回答

0

首先我会执行内部连接到外部范围内的ST_TBL,我对此有了一个加速。它降低了我的执行计划中的成本,IO成本和字节,并比较了两种变体。 我假设列PT,DISPLAYTEXT和RSC是表ST_TBL的一部分。

SELECT 
    ID, STATUS_ID, INTERVAL_ID, BEGIN_TS, END_TS, SRESULT.PT, SRESULT.DISPLAYTEXT, SRESULT.RSC 
FROM 
(
    SELECT 
     ID, INTERVAL_ID, INTERVAL_TBL.STATUS_ID, BEGIN_TS, END_TS, 
     RANK() OVER (ORDER BY BEGIN_TS DESC) MY_RANK 
    FROM INTERVAL_TBL 
    WHERE ID = '<id>' 
) SRESULT 
INNER JOIN ST_TBL ON ST_TBL.STATUS_ID = SRESULT.STATUS_ID 
WHERE MY_RANK <= 10