【问题标题】:Oracle database - Does count(0) run faster than rownum < 500Oracle 数据库 - count(0) 是否比 rownum < 500 运行得快
【发布时间】:2015-11-04 08:18:30
【问题描述】:

我想优化我的数据库上的某个查询,如果结果 > 500 则不要运行该查询。

从这 2 个中最快的方法是什么:

1)

list = createNativeQuery("select count(0) from (select * from table where rownum <= 501)")
if(list.size() > 500) throw error;
else runQuery();

或 2)

list = createNativeQuery("select * from table where rownum <= 501")
if(list.size() > 500) throw error;

总体而言,计数查询是否比实际获取所有行并计算结果的大小更快并经过优化以运行得更快?

编辑: 在第一种情况下,如果 count(0) 返回 size

【问题讨论】:

  • 第二个查询返回多条记录,而第一个查询只返回一条记录。你怎么能比较他们?这个查询呢:select count(*) from table where rownum &lt;= 501
  • 不要试图通过制定规则来调整性能。这甚至是性能成为问题的领域吗?如果是这样,当行数少于 500 行时性能更重要还是行数更多时性能更重要?这些行数中哪一个更常见?
  • 我觉得还是让数据库统计行数比较好。在java中获取记录只是增加了不必要的网络使用。
  • 在第一种情况下,如果count
  • @Alex 这两个查询大致相似,但这并不是故事的结尾。网络必须处理 select * 查询中的许多记录,但只需要处理 select count(0) 查询中的 1 条记录。

标签: mysql database oracle count rownum


【解决方案1】:

第一种方法更好,因为您不会从表中选择行到客户端 在 SQL Plus 中查看:

第一个:

SQL> SET AUTOTRACE ON STATISTICS
SQL> select count(0) from (select * from all_tables where rownum <= 501);

  COUNT(0)
----------
       501


Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
       1606  consistent gets
          0  physical reads
          0  redo size
        423  bytes sent via SQL*Net to client
        419  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          1  sorts (memory)
          0  sorts (disk)
          1  rows processed

第二: 已选择 418 行。

select * from table where rownum <= 501;
Statistics
----------------------------------------------------------
      9  recursive calls
      0  db block gets
    855  consistent gets
      0  physical reads
      0  redo size
  25012  bytes sent via SQL*Net to client
    716  bytes received via SQL*Net from client
     29  SQL*Net roundtrips to/from client
      1  sorts (memory)
      0  sorts (disk)
    418  rows processed

SQL>

注意字节数

423 in 1st approach vs 25012 in 2nd

第三 我不确定您项目的逻辑,但也许

select count(*) from all_tables

是最容易获得行数的方法,如果是 >501,则根本不要运行查询

SQL> select count(*) from all_tables;

  COUNT(*)
----------
      1711


Statistics
----------------------------------------------------------
          8  recursive calls
          0  db block gets
       2557  consistent gets
          0  physical reads
        124  redo size
        423  bytes sent via SQL*Net to client
        419  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          1  sorts (memory)
          0  sorts (disk)
          1  rows processed

SQL>

【讨论】:

    【解决方案2】:

    比较以下两个查询:

    select * from table where rownum <= 501
    select count(*) from table where rownum <= 501
    

    一般来说,这两种情况都需要数据库从表中访问 501 条(或更少)记录。从这个角度来看,这两个查询的性能应该大致相似。我不认为select count(*) 的表现会比select * 差。 然而,通过调用第一个查询,您可能会将大量数据发送回您的 Java 代码。这本身就有成为性能问题的风险。数据库非常擅长计算记录,但 Java 代码则不然。第二个查询似乎更适合您的用例。

    请查看this great SO post了解更多信息。

    【讨论】:

    • 这两种情况都需要数据库访问表中的每条记录。这是错误。两个查询都将触及表中最多 501 条记录。这就是存在 rownum 的原因。
    猜你喜欢
    • 2014-03-12
    • 2016-07-14
    • 2011-07-12
    • 2011-09-25
    • 1970-01-01
    • 2011-12-18
    • 2012-08-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多