Oracle中更快的替代方法是SELECT COUNT(*)FROM sometable

Eli*_*ght 59 oracle count

我注意到在Oracle中,查询

SELECT COUNT(*) FROM sometable;
Run Code Online (Sandbox Code Playgroud)

对于大型桌来说非常慢.它似乎是数据库,它实际上遍历每一行并一次递增一个计数器.我认为表中某处有一个计数器表有多少行.

因此,如果我想检查Oracle中表中的行数,那么最快的方法是什么?

Jef*_*emp 58

如果您只想粗略估计,可以从样本中推断:

SELECT COUNT(*) * 100 FROM sometable SAMPLE (1);

为了提高速度(但精度较低),您可以减小样本量:

SELECT COUNT(*) * 1000 FROM sometable SAMPLE (0.1);

为了获得更高的速度(但精度更高),您可以使用逐块采样:

SELECT COUNT(*) * 100 FROM sometable SAMPLE BLOCK (1);

  • 不,不幸的是,SAMPLE子句仅适用于基表. (4认同)
  • 除了实际运行查询并计算返回的记录数量之外,我能想到的唯一方法是使用Oracle的优化器统计数据 - 即查看解释计划顶层的基数 - 但我只期望它们有点代表一个数量级,我不能认为这是任何用例的合理选择. (2认同)

小智 49

这适用于大型表格.

SELECT NUM_ROWS FROM ALL_TABLES WHERE TABLE_NAME = 'TABLE_NAME_IN_UPPERCASE';
Run Code Online (Sandbox Code Playgroud)

对于中小型表,以下都可以.

SELECT COUNT(Primary_Key) FROM table_name;
Run Code Online (Sandbox Code Playgroud)

干杯,

  • 这不会实时更新,根据您的数据库可能根本不会更新.http://docs.oracle.com/cd/B28359_01/server.111/b28320/statviews_2105.htm#REFRN20286 (12认同)
  • 确保`table_name`的格式为''TABLE_NAME' (6认同)

Vin*_*rat 29

想一想:数据库真的必须去每一行才能做到这一点.在多用户环境中,我COUNT(*)可能与您的不同COUNT(*).为每个会话设置一个不同的计数器是不切实际的,因此你可以按字面计算行数.大多数情况下,你的查询中都会有WHERE子句或JOIN,所以你的假设计数器具有实用价值.

但是有一些方法可以加快速度:如果在NOT NULL列上有一个INDEX,Oracle将计算索引的行而不是表.在适当的关系模型中,所有表都有一个主键,因此COUNT(*)将使用主键的索引.

位图索引具有NULL行的条目,因此如果有一个位图索引,COUNT(*)将使用位图索引.

  • @Eli:索引键越小,查询越快.如果你的表很大,那么`COUNT(*)`无论如何都需要时间.在其他答案中查看一些替代`COUNT(*)`的建议(在物化视图中记录结果,在样本上做COUNT,......) (3认同)
  • 我在这个表上有 4 列的主键,每一列都不是 NULL,并且执行 COUNT(*) 仍然需要 41 秒。索引是否必须位于单个列上才能快速执行 COUNT(*) 查询? (2认同)

APC*_*APC 13

如果表在NOT NULL列上有索引,则COUNT(*)将使用该列.否则,它将执行全表扫描.请注意,索引不必是UNIQUE,它必须是NOT NULL.

这是一张桌子......

SQL> desc big23
 Name                                      Null?    Type
 ----------------------------------------- -------- ---------------------------
 PK_COL                                    NOT NULL NUMBER
 COL_1                                              VARCHAR2(30)
 COL_2                                              VARCHAR2(30)
 COL_3                                              NUMBER
 COL_4                                              DATE
 COL_5                                              NUMBER
 NAME                                               VARCHAR2(10)

SQL>
Run Code Online (Sandbox Code Playgroud)

首先,我们将做一个没有索引的计数....

SQL> explain plan for
  2      select count(*) from big23
  3  /

Explained.

SQL> select * from table(dbms_xplan.display)
  2  /
select * from table)dbms_xplan.display)

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------
Plan hash value: 983596667

--------------------------------------------------------------------
| Id  | Operation          | Name  | Rows  | Cost (%CPU)| Time     |
--------------------------------------------------------------------
|   0 | SELECT STATEMENT   |       |     1 |  1618   (1)| 00:00:20 |
|   1 |  SORT AGGREGATE    |       |     1 |            |          |
|   2 |   TABLE ACCESS FULL| BIG23 |   472K|  1618   (1)| 00:00:20 |
--------------------------------------------------------------------

Note

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------
   - dynamic sampling used for this statement

13 rows selected.

SQL>
Run Code Online (Sandbox Code Playgroud)

不,我们在列上创建一个可以包含NULL条目的索引......

SQL> create index i23 on big23(col_5)
  2  /

Index created.

SQL> delete from plan_table
  2  /

3 rows deleted.

SQL> explain plan for
  2      select count(*) from big23
  3  /

Explained.

SQL> select * from table(dbms_xplan.display)
  2  /

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------
Plan hash value: 983596667

--------------------------------------------------------------------
| Id  | Operation          | Name  | Rows  | Cost (%CPU)| Time     |
--------------------------------------------------------------------
|   0 | SELECT STATEMENT   |       |     1 |  1618   (1)| 00:00:20 |
|   1 |  SORT AGGREGATE    |       |     1 |            |          |
|   2 |   TABLE ACCESS FULL| BIG23 |   472K|  1618   (1)| 00:00:20 |
--------------------------------------------------------------------

Note

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------
   - dynamic sampling used for this statement

13 rows selected.

SQL>
Run Code Online (Sandbox Code Playgroud)

最后让我们在NOT NULL列上构建索引....

SQL> drop index i23
  2  /

Index dropped.

SQL> create index i23 on big23(pk_col)
  2  /

Index created.

SQL> delete from plan_table
  2  /

3 rows deleted.

SQL> explain plan for
  2      select count(*) from big23
  3  /

Explained.

SQL> select * from table(dbms_xplan.display)
  2  /

PLAN_TABLE_OUTPUT
---------------------------------------------------------------------
Plan hash value: 1352920814

----------------------------------------------------------------------
| Id  | Operation             | Name | Rows  | Cost (%CPU)| Time     |
----------------------------------------------------------------------
|   0 | SELECT STATEMENT      |      |     1 |   326   (1)| 00:00:04 |
|   1 |  SORT AGGREGATE       |      |     1 |            |          |
|   2 |   INDEX FAST FULL SCAN| I23  |   472K|   326   (1)| 00:00:04 |
----------------------------------------------------------------------

Note

PLAN_TABLE_OUTPUT
----------------------------------------------------------------------
   - dynamic sampling used for this statement

13 rows selected.

SQL>
Run Code Online (Sandbox Code Playgroud)


Dav*_*dge 7

选项1:在非空列上存在可用于扫描的索引.或者创建基于函数的索引:

create index idx on t(0);
Run Code Online (Sandbox Code Playgroud)

然后可以扫描这个以计算.

选项2:如果已打开监视,则检查监视视图USER_TAB_MODIFICATIONS并将相关值添加/减去表统计信息.

选项3:对大型表的快速估计调用SAMPLE子句...例如......

SELECT 1000*COUNT(*) FROM sometable SAMPLE(0.1); 
Run Code Online (Sandbox Code Playgroud)

选项4:使用物化视图来维护计数(*).虽然强大的药物.

嗯...


tui*_*oel 5

您可以创建快速刷新物化视图来存储计数.

例:

create table sometable (
id number(10) not null primary key
, name varchar2(100) not null);

create materialized view log on sometable with rowid including new values;

create materialized view sometable_count
refresh on commit
as
select count(*) count
from   sometable;

insert into sometable values (1,'Raymond');
insert into sometable values (2,'Hans');

commit;

select count from sometable_count; 
Run Code Online (Sandbox Code Playgroud)

它会减慢桌面上的突变,但计数会变得更快.