【问题标题】:Oracle view performance with rownum使用 rownum 的 Oracle 查看性能
【发布时间】:2012-09-13 03:58:47
【问题描述】:

我正在使用 Oracle 10g,并且我有一个连接两个大表(数百万条记录)的视图。我正在尝试为用户选择有限的数据“样本”,如下所示:

select * from VIEW_NAME where ROWNUM < 5; 

它很慢,我认为不应该,因为我只需要几行结果,所以Oracle不应该计算全连接。

要求是用户应该能够以交互方式指定返回的行数(结果中的哪些行并不重要)。有什么办法可以做到这一点? (使用 rownum 或其他方法)

(我可以更改视图定义或构建最终 SQL 的方式,但据我所知,我无法将有关所需行数的信息动态传递给视图)

编辑:视图定义非常简单,如下所示:

CREATE OR REPLACE VIEW VIEW_NAME AS
(
    select
    e.id as ID,
    e.somefield as something,
    ... (some similar selects from e)
    c.field as anotherthing,
   ... (lots of other fields from c)
    from SCHEMA.TABLE1 e
    inner join SCHEMA.TABLE2 c on e.key = c.key
)

解释计划提到了两个表的全表访问,这并不奇怪,因为只返回前几行应该不会花费很长时间。

EDIT2:这是完整的计划

SQL> select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 2644394598

----------------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                 | Name        | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     | Pstart| Pstop |    TQ  |IN-OUT| PQ Distrib |
----------------------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT          |             |     4 |  1252 |       | 43546   (1)| 00:08:43 |       |       |        |      |            |
|*  1 |  COUNT STOPKEY            |             |       |       |       |            |          |       |       |        |      |            |
|   2 |   PX COORDINATOR          |             |       |       |       |            |          |       |       |        |      |            |
|   3 |    PX SEND QC (RANDOM)    | :TQ10002    |   696K|   207M|       | 43546   (1)| 00:08:43 |       |       |  Q1,02 | P->S | QC (RAND)  |
|*  4 |     COUNT STOPKEY         |             |       |       |       |            |          |       |       |  Q1,02 | PCWC |            |
|*  5 |      HASH JOIN BUFFERED   |             |   696K|   207M|    49M| 43546   (1)| 00:08:43 |       |       |  Q1,02 | PCWP |            |

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------
|   6 |       BUFFER SORT         |             |       |       |       |            |          |       |       |  Q1,02 | PCWC |            |
|   7 |        PX RECEIVE         |             |   696K|    90M|       |  5137   (1)| 00:01:02 |       |       |  Q1,02 | PCWP |            |
|   8 |         PX SEND HASH      | :TQ10000    |   696K|    90M|       |  5137   (1)| 00:01:02 |       |       |        | S->P | HASH       |
|   9 |          TABLE ACCESS FULL| TABLE1      |   696K|    90M|       |  5137   (1)| 00:01:02 |       |       |        |      |            |
|  10 |       PX RECEIVE          |             |   892K|   149M|       |  5260   (1)| 00:01:04 |       |       |  Q1,02 | PCWP |            |
|  11 |        PX SEND HASH       | :TQ10001    |   892K|   149M|       |  5260   (1)| 00:01:04 |       |       |  Q1,01 | P->P | HASH       |
|  12 |         PX BLOCK ITERATOR |             |   892K|   149M|       |  5260   (1)| 00:01:04 |     1 |   140 |  Q1,01 | PCWC |            |
|  13 |          TABLE ACCESS FULL| TABLE2      |   892K|   149M|       |  5260   (1)| 00:01:04 |     1 |   140 |  Q1,01 | PCWP |            |
----------------------------------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):

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

   1 - filter(ROWNUM<5)
   4 - filter(ROWNUM<5)
   5 - access("E"."KEY"="C"."KEY")

27 rows selected.

【问题讨论】:

  • 视图到底在做什么?您可以发布视图的来源吗?该语句的查询计划是什么? “非常慢”对您意味着什么 - 您是说返回结果需要几个小时吗?分钟? 5 秒什么时候你认为应该是亚秒级响应?
  • 测试数据库中非常慢的是 15 秒,但在生产数据库中(我无法访问那里)有 3 倍多的数据。我会尽快为这个问题添加更多信息。
  • 你能发布实际的查询计划吗?它是在做哈希连接吗?嵌套循环连接?当您说“来自 e 的类似选择”时,您是在谈论内联查询吗?或者只是引用e 中的列?
  • 它正在做一个哈希连接,它只是简单地引用 e 中的列,没有隐藏的子选择或其他技巧......我正在尝试发布整个计划。
  • iirc - 在将 rownum 标准应用于返回的结果集之前,rownum 始终计算完整的结果集。换句话说,通过使用 ROWNUM 进行限制,您不会看到任何性能提升。

标签: database performance oracle view rownum


【解决方案1】:

我会根据 GuiGi 的回答查看 /*+ NOPARALLEL */ 提示的作用。要尝试的另一件事是查看为此生成的计划:

select /*+ FIRST_ROWS(10)*/ * from VIEW_NAME where ROWNUM < 5;

【讨论】:

  • FIRST_ROWS 显着提高了性能(达到 0.05 秒),非常感谢!
  • rownum 谓词隐含第一行提示(在以后的版本中)
【解决方案2】:

您可以尝试在查询中添加 NOPARALLEL 提示。

select /*+ NOPARALLEL */ * from VIEW_NAME where ROWNUM < 5; 

这是一种选择并行执行但可能不利于性能的情况,因为它会使用更多的 CPU 和 I/O。

【讨论】:

    【解决方案3】:

    你有连接索引吗(索引嵌套循环应该是优化器选择的访问路径)?尝试禁用 hash_join(与 sort_merge_join 一起)以查看替代平面的成本是多少,如果您看到普通的嵌套循环,那么优化器由于某种原因忽略了索引。

    当使用内联视图定义的视图调整查询时,请尝试提示您想要的访问路径。当您发现魔法提示(例如基数)时,有时可以将它们移到外部查询块中(对于以后的 oracle 版本尤其如此)。

    【讨论】:

      【解决方案4】:

      你也可以试试:

      select * FROM 
      (SELECT rownum ROW_NUMBER, YOUR_VIEW.* FROM  YOUR_VIEW) 
      WHERE ROW_NUMBER> 2
      

      【讨论】:

        猜你喜欢
        • 2012-02-26
        • 2014-05-23
        • 2013-10-22
        • 1970-01-01
        • 2010-10-08
        • 2011-09-30
        • 2020-05-11
        • 2017-07-05
        相关资源
        最近更新 更多