ORACLE DELETE数据慢的案例

简介:

   今天遇到一个有意思的案例,一开发同事告诉我他删除一个表的记录非常慢,已经快1个多小时了还没有完成。而且删除的记录只有1百多条。真是大跌眼镜的一件 事情。最后发现该表与多个表有外键关联关系(这个表即是主表、又是从表),最后我禁用引用该表的外键约束后。一秒内删除了记录。然后启用外键约束关系。下 面记录、分析一下解决过程的思路(下面是在测试环境的记录,数据量不一样)。

我 去处理这个问题时,首先怀疑可能是SQL的阻塞、触发器、外键约束、高水位线等因素中的某一个导致DELETE操作慢,于是我打算一个一个排除,我先试着 删除一条记录,然后去检查SQL的阻塞情况,结果使用下面SQL语句并没有发现SQL被阻塞。于是SQL的阻塞导致DELETE慢的原因被我排除了。

SELECT '节点 ' || A.INST_ID || ' SESSION ' || A.SID || ',' || A_S.SERIAL# ||
       ' 阻塞了 节点 ' || B.INST_ID || ' SESSION ' || B.SID || ',' || B_S.SERIAL# BLOCKINFO,
       A.INST_ID,
       A_S.SID,
       A_S.SCHEMANAME,
       A_S.MODULE,
       A_S.STATUS,
       A.TYPE LOCK_TYPE,
       A.ID1,
       A.ID2,
       DECODE(A.LMODE,
              0,
              'NONE',
              1,
              NULL,
              2,
              'ROW-S (SS)',
              3,
              'ROW-X (SX)',
              4,
              'SHARE (S)',
              5,
              'S/ROW-X (SSX)',
              6,
              'EXCLUSIVE (X)') LOCK_MODE,
       
       '后为被阻塞信息' ,
       B.INST_ID BLOCKED_INST_ID,
       B_S.SID BLOCKED_SID,
       B.TYPE BLOCKED_LOCK_TYPE,
       DECODE(B.REQUEST,
              0,
              'NONE',
              1,
              NULL,
              2,
              'ROW-S (SS)',
              3,
              'ROW-X (SX)',
              4,
              'SHARE (S)',
              5,
              'S/ROW-X (SSX)',
              6,
              'EXCLUSIVE (X)') BLOCKED_LOCK_REQUEST,
       B_S.SCHEMANAME BLOCKED_SCHEMANAME,
       B_S.MODULE BLOCKED_MODULE,
       B_S.STATUS BLOCKED_STATUS,
       B_S.SQL_ID BLOCKED_SQL_ID,
       OBJ.OWNER BLOCKED_OWNER,
       OBJ.OBJECT_NAME BLOCKED_OBJECT_NAME,
       OBJ.OBJECT_TYPE BLOCKED_OBJECT_TYPE,
       CASE
          WHEN B_S.ROW_WAIT_OBJ# <> -1 THEN
             DBMS_ROWID.ROWID_CREATE(1,
                                     OBJ.DATA_OBJECT_ID,
                                     B_S.ROW_WAIT_FILE#,
                                     B_S.ROW_WAIT_BLOCK#,
                                     B_S.ROW_WAIT_ROW#) 
          ELSE 
            '-1' 
          END BLOCKED_ROWID, --THE BLOCKED ROWID
       DECODE(OBJ.OBJECT_TYPE,
              'TABLE',
              'SELECT * FROM ' || OBJ.OWNER || '.' || OBJ.OBJECT_NAME ||
              ' WHERE ROWID=''' ||
              DBMS_ROWID.ROWID_CREATE(1,
                                      OBJ.DATA_OBJECT_ID,
                                      B_S.ROW_WAIT_FILE#,
                                      B_S.ROW_WAIT_BLOCK#,
                                      B_S.ROW_WAIT_ROW#) || '''',
              NULL)  BLOCKED_DATA_QUERYSQL
  FROM GV$LOCK     A,
       GV$LOCK     B,
       GV$SESSION  A_S,
       GV$SESSION  B_S,
       DBA_OBJECTS OBJ
 WHERE A.ID1 = B.ID1
   AND A.ID2 = B.ID2
   AND A.BLOCK > 0 --BLOCK THE OTHER SQL
   AND B.REQUEST > 0
   AND ((A.INST_ID = B.INST_ID AND A.SID <> B.SID) OR
       (A.INST_ID <> B.INST_ID))
   AND A.SID = A_S.SID
   AND A.INST_ID = A_S.INST_ID
   AND B.SID = B_S.SID
   AND B.INST_ID = B_S.INST_ID
   AND B_S.ROW_WAIT_OBJ# = OBJ.OBJECT_ID(+)
 ORDER BY A.INST_ID,A.SID;

接下来,我检查了该表的的触发器,结果并没有发现DELETE触发器。也就是说DELETE操作并不会触发任何触发器。触发器导致DELETE慢的怀疑也可以排除掉了。

SELECT * FROM DBA_TRIGGERS WHERE TABLE_NAME='INV_LOCATION_PALLETS'

我用show_space检查了一下这个表的高水位线,发现并没有问题,不需要收缩高水位线。高水位线这个因素也可以排除了。只剩下外键约束的影响了。于是检查了一下有哪些表是该表的从表,如下所示

SELECT /*+RULE*/ D.CONSTRAINT_NAME PK_NAME,
                 D.TABLE_NAME 
                 || '.' 
                 || D.COLUMN_NAME  PK_COLUMN,
                 A.CONSTRAINT_TYPE,
                 B.CONSTRAINT_NAME FK_NAME,
                 B.TABLE_NAME 
                 || '.' 
                 || B.COLUMN_NAME  FK_COLUMN
FROM   DBA_CONSTRAINTS A 
       JOIN DBA_CONS_COLUMNS B 
         ON A.CONSTRAINT_NAME = B.CONSTRAINT_NAME
            AND A.OWNER = B.OWNER
       JOIN DBA_CONSTRAINTS C 
         ON A.R_CONSTRAINT_NAME = C.CONSTRAINT_NAME
            AND A.R_OWNER = C.OWNER
       JOIN DBA_CONS_COLUMNS D 
         ON C.CONSTRAINT_NAME = D.CONSTRAINT_NAME
            AND C.OWNER = D.OWNER
WHERE  D.TABLE_NAME = 'INV_LOCATION_PALLETS' 

clip_image001

有时候也可以用下面语句查看引用这个表的外键引用关系

SELECT * FROM DBA_CONSTRAINTS WHERE R_CONSTRAINT_NAME='PK_INV_LOCATION_PALLETS'

如上所示,INV_LOCATION_PALLETS这个表有三个从表,而这里面有个表的记录很大,大概2千多万。所以导致DELETE操作很慢。

我们可以用跟踪当前会话,查看一下DELETE操作,就会发现它会去处理从表,检查从表有没有对应的记录,而这个外键刚好也没有索引(下面是使用tkprof命令格式化的内容)。在这篇Delete the data on the table very slow(删除数据慢)博客里面跟深入的介绍、分析了删除表删除数据慢的原因。在此不做过多赘述了。

DELETE INVENTORY.INV_LOCATION_PALLETS  
WHERE
 PALLET_ID =1039928
 
 
call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.00       0.00          0          0          0           0
Execute      1      0.00       0.00          0          3         26           1
Fetch        0      0.00       0.00          0          0          0           0
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        2      0.00       0.01          0          3         26           1
 
Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 5  
 
Rows     Row Source Operation
-------  ---------------------------------------------------
      1  DELETE  INV_LOCATION_PALLETS (cr=752149 pr=735050 pw=0 time=7550289 us)
      1   INDEX UNIQUE SCAN PK_INV_LOCATION_PALLETS (cr=3 pr=0 pw=0 time=38 us)(object id 59532)
 
********************************************************************************
 
select /*+ all_rows */ count(1) 
from
 "INVENTORY"."INV_REQ_HD" where "TO_PALLET_ID" = :1
 
 
call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.00       0.00          0          0          0           0
Execute      1      0.00       0.00          0          0          0           0
Fetch        1      0.75       0.74      70540      78205          0           1
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        3      0.75       0.74      70540      78205          0           1
 
Misses in library cache during parse: 0
Optimizer mode: ALL_ROWS
Parsing user id: SYS   (recursive depth: 1)
 
Rows     Row Source Operation
-------  ---------------------------------------------------
      1  SORT AGGREGATE (cr=78205 pr=70540 pw=0 time=743169 us)
      0   TABLE ACCESS FULL INV_REQ_HD (cr=78205 pr=70540 pw=0 time=743155 us)
 
********************************************************************************
 
select /*+ all_rows */ count(1) 
from
 "INVENTORY"."INV_REQ_HD" where "FROM_PALLET_ID" = :1
 
 
call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.00       0.00          0          0          0           0
Execute      1      0.00       0.00          0          0          0           0
Fetch        1      0.69       0.67      70528      78205          0           1
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        3      0.69       0.68      70528      78205          0           1
 
Misses in library cache during parse: 0
Optimizer mode: ALL_ROWS
Parsing user id: SYS   (recursive depth: 1)
 
Rows     Row Source Operation
-------  ---------------------------------------------------
      1  SORT AGGREGATE (cr=78205 pr=70528 pw=0 time=680000 us)
      0   TABLE ACCESS FULL INV_REQ_HD (cr=78205 pr=70528 pw=0 time=679987 us)
 
********************************************************************************
 
select /*+ all_rows */ count(1) 
from
 "INVENTORY"."INV_REQ_LINES" where "TO_PALLET_ID" = :1
 
 
call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.00       0.00          0          0          0           0
Execute      1      0.00       0.00          0          0          0           0
Fetch        1      3.30       3.23     296991     297868          0           1
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        3      3.30       3.23     296991     297868          0           1
 
Misses in library cache during parse: 0
Optimizer mode: ALL_ROWS
Parsing user id: SYS   (recursive depth: 1)
 
Rows     Row Source Operation
-------  ---------------------------------------------------
      1  SORT AGGREGATE (cr=297868 pr=296991 pw=0 time=3232134 us)
      0   TABLE ACCESS FULL INV_REQ_LINES (cr=297868 pr=296991 pw=0 time=3232122 us)
 
********************************************************************************
 
select /*+ all_rows */ count(1) 
from
 "INVENTORY"."INV_REQ_LINES" where "FROM_PALLET_ID" = :1
 
 
call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.00       0.00          0          0          0           0
Execute      1      0.00       0.00          0          0          0           0
Fetch        1      2.94       2.88     296991     297868          0           1
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        3      2.94       2.88     296991     297868          0           1
 
Misses in library cache during parse: 0
Optimizer mode: ALL_ROWS
Parsing user id: SYS   (recursive depth: 1)
 
Rows     Row Source Operation
-------  ---------------------------------------------------
      1  SORT AGGREGATE (cr=297868 pr=296991 pw=0 time=2885783 us)
      0   TABLE ACCESS FULL INV_REQ_LINES (cr=297868 pr=296991 pw=0 time=2885772 us)
 
********************************************************************************
 
begin
  sys.dbms_output.get_line(line => :line, status => :status);
end;
 
call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        4      0.00       0.00          0          0          0           0
Execute      4      0.00       0.00          0          0          0           4
Fetch        0      0.00       0.00          0          0          0           0
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        8      0.00       0.00          0          0          0           4
 
Misses in library cache during parse: 0
Optimizer mode: ALL_ROWS
Parsing user id: 5  

clip_image002

  

相关文章
|
4月前
|
SQL 运维 Oracle
【迁移秘籍揭晓】ADB如何助你一臂之力,轻松玩转Oracle至ADB的数据大转移?
【8月更文挑战第27天】ADB(Autonomous Database)是由甲骨文公司推出的自动化的数据库服务,它极大简化了数据库的运维工作。在从传统Oracle数据库升级至ADB的过程中,数据迁移至关重要。
78 0
|
1月前
|
存储 Oracle 关系型数据库
【赵渝强老师】Oracle的还原数据
Oracle数据库中的还原数据(也称为undo数据或撤销数据)存储在还原表空间中,主要用于支持查询的一致性读取、实现闪回技术和恢复失败的事务。文章通过示例详细介绍了还原数据的工作原理和应用场景。
【赵渝强老师】Oracle的还原数据
|
4月前
|
数据采集 Oracle 关系型数据库
实时计算 Flink版产品使用问题之怎么实现从Oracle数据库读取多个表并将数据写入到Iceberg表
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
|
21天前
|
Oracle 关系型数据库 数据库
Oracle数据恢复—Oracle数据库文件有坏快损坏的数据恢复案例
一台Oracle数据库打开报错,报错信息: “system01.dbf需要更多的恢复来保持一致性,数据库无法打开”。管理员联系我们数据恢复中心寻求帮助,并提供了Oracle_Home目录的所有文件。用户方要求恢复zxfg用户下的数据。 由于数据库没有备份,无法通过备份去恢复数据库。
|
27天前
|
存储 Oracle 关系型数据库
oracle数据恢复—Oracle数据库文件大小变为0kb的数据恢复案例
存储掉盘超过上限,lun无法识别。管理员重组存储的位图信息并导出lun,发现linux操作系统上部署的oracle数据库中有上百个数据文件的大小变为0kb。数据库的大小缩水了80%以上。 取出&并分析oracle数据库的控制文件。重组存储位图信息,重新导出控制文件中记录的数据文件,发现这些文件的大小依然为0kb。
|
13天前
|
存储 Oracle 关系型数据库
服务器数据恢复—华为S5300存储Oracle数据库恢复案例
服务器存储数据恢复环境: 华为S5300存储中有12块FC硬盘,其中11块硬盘作为数据盘组建了一组RAID5阵列,剩下的1块硬盘作为热备盘使用。基于RAID的LUN分配给linux操作系统使用,存放的数据主要是Oracle数据库。 服务器存储故障: RAID5阵列中1块硬盘出现故障离线,热备盘自动激活开始同步数据,在同步数据的过程中又一块硬盘离线,RAID5阵列瘫痪,上层LUN无法使用。
|
2月前
|
存储 Oracle 关系型数据库
数据库数据恢复—Oracle ASM磁盘组故障数据恢复案例
Oracle数据库数据恢复环境&故障: Oracle ASM磁盘组由4块磁盘组成。Oracle ASM磁盘组掉线 ,ASM实例不能mount。 Oracle数据库故障分析&恢复方案: 数据库数据恢复工程师对组成ASM磁盘组的磁盘进行分析。对ASM元数据进行分析发现ASM存储元数据损坏,导致磁盘组无法挂载。
|
1月前
|
SQL Oracle 关系型数据库
【赵渝强老师】Oracle的联机重做日志文件与数据写入过程
在Oracle数据库中,联机重做日志文件记录了数据库的变化,用于实例恢复。每个数据库有多组联机重做日志,每组建议至少有两个成员。通过SQL语句可查看日志文件信息。视频讲解和示意图进一步解释了这一过程。
|
1月前
|
SQL Oracle 关系型数据库
【赵渝强老师】Oracle的数据文件
在Oracle数据库中,数据库由多个表空间组成,每个表空间包含多个数据文件。数据文件存储实际的数据库数据。查询时,如果内存中没有所需数据,Oracle会从数据文件中读取并加载到内存。可通过SQL语句查看和管理数据文件。附有视频讲解及示例。
|
3月前
|
Oracle 关系型数据库 数据库
数据库数据恢复—Oracle数据库文件出现坏块的数据恢复案例
打开oracle数据库报错“system01.dbf需要更多的恢复来保持一致性,数据库无法打开”。 数据库没有备份,无法通过备份去恢复数据库。用户方联系北亚企安数据恢复中心并提供Oracle_Home目录中的所有文件,急需恢复zxfg用户下的数据。 出现“system01.dbf需要更多的恢复来保持一致性”这个报错的原因可能是控制文件损坏、数据文件损坏,数据文件与控制文件的SCN不一致等。数据库恢复工程师对数据库文件进一步检测、分析后,发现sysaux01.dbf文件损坏,有坏块。 修复并启动数据库后仍然有许多查询报错,export和data pump工具使用报错。从数据库层面无法修复数据库。
数据库数据恢复—Oracle数据库文件出现坏块的数据恢复案例

推荐镜像

更多