Oracle TOP优化

时间:2017-05-12 07:31:55

标签: sql oracle query-optimization database-performance top-n

我在优化声明方面遇到了麻烦。相应的表(INTERVAL_TBL)包含大约11.000.000行,这导致该语句在我的测试系统上花费大约8秒。即使在专用的Oracle服务器(24GB RAM,17GB数据库大小)上,也需要大约4-5秒。

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

首先,我想知道是否有办法优化Statement(选择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
  • 已加入子集中的行,ID为:530.073

理想情况下,它会降低到大约几毫秒。这是该语句在具有10.000.000行的MS SQL Server中所采用的内容。

1 个答案:

答案 0 :(得分: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