Oracle 和类似 MS-SQL 的行计数

Cha*_*rns 5 performance oracle statistics count

我的应用程序通常需要准确但可能不完美的行数。十亿行的表经常会被频繁写入,所以“完美”是定义和时间的问题。

Microsoft SQL 保留了非常好的元数据,允许进行如下查询:

SELECT SUM(rows) FROM sys.partitions
WHERE object_id = object_id('TABLE_NAME') 
AND index_id < 2;
Run Code Online (Sandbox Code Playgroud)

还有其他具有不同元数据的方法)。这提供了近乎完美的行数,可能会忽略某些正在进行的事务或其他细节。这些技术适用于除最苛刻的情况之外的所有情况,并且几乎是即时的。

在 Oracle 中,我们可以使用统计信息:

SELECT num_rows
FROM all_tables
WHERE table_name = 'TABLE_NAME'
Run Code Online (Sandbox Code Playgroud)

这是不可靠的,因为如果完全收集了统计信息,根据 DBA 策略,它们通常已经过时。

我可以牺牲显着的准确性来使用采样来提高速度:

SELECT COUNT(*) * 1000 rc_sampled FROM lot_size SAMPLE(.1) SEED(42)
Run Code Online (Sandbox Code Playgroud)

然而,这是不准确的设计,还是相当慢(115秒在500M行测试),并且几乎是无用的,当应用程序不已经有一个行数的估计。在一个有 800 行的表上运行该 SQL 就像问,“那个糖果棒的价格是多少,给予或接受 75.00 美元?”)

Oracle 是否提供了一种实用的方法来获得任意表的准确、快速的行数,例如 Microsoft SQL 和其他提供的表?

Bal*_*app 3

Oracle 数据库在内部跟踪自上次收集统计信息以来表上受 DML/DDL 操作影响的行数。

我从来没有用过它来做任何重要的事情,但你可以尝试一下。首先将监控数据从内存刷新到底层表,这样就可以查询了(这也是周期性发生的):

exec dbms_stats.flush_database_monitoring_info;
Run Code Online (Sandbox Code Playgroud)

然后选择行数并通过插入/删除进行调整:

select
  t.num_rows - i.deletes + i.inserts 
from
  user_tables t 
  join user_tab_modifications i on t.table_name = i.table_name 
where
  t.table_name = 'TABLE_NAME'
;
Run Code Online (Sandbox Code Playgroud)

当然,这并不是 100% 准确,例如,如果数据库在自动刷新之前重新启动,该信息就会丢失。

但是您应该拥有有关更改的表的最新统计信息。