oracle - 表记录数不正确(*)

标签 oracle merge procedure

我正在尝试对 Oracle 中的表进行计数。当我运行一个非常简单的计数时,例如:

SELECT COUNT(*) FROM EDW.SCADA_VALUE_HIST; --Returns [114315627]

它返回一个看起来正确的结果(在查询外部的括号中)。现在,当我将过滤条件应用于同一个表时,它返回的行数比表的 count(*) 更多:

SELECT COUNT(*) FROM EDW.SCADA_VALUE_HIST 
WHERE UPDT_VAL_EFF_DTTM <= (SYSDATE-5); --Returns [131416178]

此外,我继续检查了表的统计信息(sql Developer 中的详细信息),它返回了更高的计数 [146436917](我知道这不是 100% 准确,但它应该是合理的)锻炼)。我没有看到过滤条件如何返回比表本身更多的计数行。详细信息如下:

  1. 该查询在同一数据库中运行,每次运行时间为 10 秒 其他
  2. 该表每 10 分钟通过 a 插入约 60k 行 预定工作
  3. 计划作业执行一个使用 合并(下)
  4. UPDT_VAL_EFF_DTTM 是日期字段,且此列不可为空
  5. 该表总共包含 5 个索引(复合主键(4 个字段)和唯一索引,后跟 4 个非唯一索引
  6. 它在 Oracle 11gr2 上运行
  7. 数据库正在运行具有 3 个物理备用数据库和 1 个主数据库的 DataGuard 环境

    create or replace PROCEDURE UPDATE_VALUE_HIST AS
        v_date VARCHAR2(16);
        g_counter NUMBER(10,0) := 0;
        g_insertspeed NUMBER (10,0) := 1000;
        g_inserttime NUMBER (10,0) := 20; 
    BEGIN
      BEGIN
    
        MERGE INTO EDW.SCADA_VALUE_HIST SVH  
        USING 
       (SELECT
           SV.COL1,SV.COL2,SD.COL3,SD.COL4,
           SVD.COL5,SVD.COL6,SVD.COL7,SV.COL8,
           SVT.COL9 AS VALUE_TYPE_NAME,SV.COL10,SD.COL11,
           SYSDATE as UPDT_VAL_EFF_DTTM,'U',SV.COL13,SV.COL14
        FROM SCHEMA.T1 SV,
             SCHEMA.T2 SVD,
             SCHEMA.T3 SVT,
             SCHEMA.T4 SD
        WHERE SV.FIELD1= SVD.FIELD1
        AND SVD.FIELD2= SVT.FIELD2
        AND SD.FIELD3= SVD.FIELD3
        AND SV.FIELD4 IS NOT NULL) B
       ON (
        SVH.FIELD1= B.FIELD1
        AND SVH.FIELD2= B.FIELD2
        AND SVH.FIELD3= B.FIELD3
        AND SVH.FIELD4 = B.FIELD4 
        )
      WHEN NOT MATCHED
        THEN
           INSERT (COL1, COL2, COL3, COL4, COL5, COL6, COL7, COL8, 
             COL9, COL10, COL11, SYSDATE, 'U', COL13, COL14);
    
      COMMIT;  
    
      END;                
    END;
    

我尝试过谷歌搜索几次,但计数帖子中的大多数错误都涉及连接和过滤条件。这对我来说是一个非常奇怪的事情。

编辑:

解释第一个查询的计划:

选择语句 -> 排序(聚合) -> 索引(对对象 PK 进行快速全面扫描)

基数:1 -> 1 -> 146436917 费用:85031

解释第二个查询的计划:

选择 -> 排序(聚合) -> 索引(对不同于 PK(过滤谓词索引)的对象索引进行快速完整扫描) -> 过滤谓词 -> UPDT_VAL_EFF_DTTM

基数:1 -> 1 -> 131379677 费用:105341

最佳答案

当我看到这种情况发生时(仅一两次),这是因为索引已损坏。我们要么重建,要么删除并重新创建索引,问题就消失了。

这只是一个轶事,并没有解释发生了什么或为什么。但在浪费大量时间处理 Oracle 支持之前,您需要先尝试这些“糟糕”的解决方案。现在花 5 分钟来重建它,您可能会避免以后几天的调查。如果问题不再发生,根本原因并不重要。

关于oracle - 表记录数不正确(*),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41645275/

相关文章:

c# - 将 DLL 嵌入已编译的可执行文件中

oracle - 如何解决 Oracle DBMS_LOB 问题

sql - 删除 Redshift 中的循环

c# - asp.net Oracle 调整线程休眠

sql - Oracle SQL。带连接的递归选择

java - loadjava 不在 Oracle Instant Client 19c 中 - 我有哪些选项?

C# 通用平台音频合并或输入视频

iOS - 将两个视频合并为一个带音频的视频文件

mysql - 如何从mysql过程中的表中获取新列?

java - ojdbc7/ojdbc8 中的字符集问题与 ojdbc6 中的正确行为