我的编程空间,编程开发者的网络收藏夹
学习永远不晚

大数据量删除的思考(四)

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

大数据量删除的思考(四)

在本系列的前一期文章中,我制作了一些图,突出显示了按表扫描执行大量删除操作和按索 引范围扫描执行大量删除之间的主要区别。 根据所涉及的数据模式,选择正确的策略可能对随机I/Os 的数量、生成的undo的数量和排序所需的CPU数量产生显著影响——所有这些都可能影响执行删除所需的时间。

然而,这个简单的演示跟生产环境当中相比,生产环境当中这个情况更为复杂。所以,如果你面临着一项艰巨的任务,你需要仔细考虑如何对真正代表你要处理的系统的东西进行建模。实际上有两种不同的情况,这一点很重要。

* 当你在处理一个非常大的一次性任务时,你需要在第一时间就把它做好,一些关键性的特殊情况不要发现的太迟——尤其是如果你不允许把生产系统离线来完成这个任务任务,而且你的工作期限很紧的话。

* 当你有一份常规的、但不经常发生的、非常大的工作时,有必要了解一下哪些看起来不相关的小操作可能对运行时产生很大影响;而且,了解下一次升级可能会出现什么问题是值得的,这样您就可以预先解决任何问题。

当然,后者的一个简单例子是我对12c的简短评论,以及它通过索引快速全扫描来驱动删除的能力-这一功能在早期版本的Oracle中无法运行。在我的小示例中,一个测试将其执行计划从11g的索引全扫描更改为12c的索引快速全扫描,完成所需的时间是原来的两倍。

继续想一想——当你试图通过索引范围扫描来删除Oracle中的表或者索引时,您能想到多少事情,这可能会产生怎样的影响?

对于一个繁忙的系统,这个建议听起来不错。有时候,你会发现一个长时间运行的DML语句在运行时速度非常慢,因为事实上它涉及到数据中最近的部分,因此会受到当前变化的影响;从这一点来看,Oracle发现它必须读取undo段来获取undo数据,这使得创建与读取一致的数据块版本成为可能-它需要这样做,以便它可以检查当前和读取一致的版本的块同意哪些行应该删除。

我做的一个例子是通过“date_open”索引删除数据-因此,如何强制索引进行降序范围扫描,以便首先检查最新的数据在它有很多(或任何)时间遭受其他DML的附带损害之前?

有一个非常快捷的方法可以检验这个想法的有效性。所以我们要做的就是检查排序的行数和删除的行数我们就能知道优化是否发生了。

我的测试数据集有1000000行和4个索引(主键client_ref、date_open和date_closed索引),所以在最好的情况下,我应该看到:“sort (rows)”= 4 *行被删除。下面是我做的一个测试的总结,我想知道会发生什么:

delete  from t1 where id <= 5e6
5000000 rows deleted.
Name                                 Value                       
----                                 -----
sorts (rows)                            29

我们删除了500万行并(有效地)没有排序。当我们按降序遍历索引时,优化根本不适用—我确实检查了执行计划是否显示了我所指定的“索引范围递减扫描”。

create index t1_dt_open on t1(date_open desc) nologging tablespace test_8k_assm_2;
delete  from t1 where date_open <= add_months(sysdate, -60);
4999999 rows deleted.
Name                                 Value
----                                 -----
sorts (rows)                    20,003,449

在副作用很小的范围内,“sort (rows)”= 4 *已删除的行:所以可以使用降序索引先尝试删除较新的数据——这很好,作为一个通用特性来记住可能很有用。

让我们想象一下其他可能出错的情况。

*我在这个表上定义了一个主键——但是你可以使约束延迟,或者您可以简单地创建一个非惟一索引来保护惟一(或主键)约束。如果我们试图通过主键索引删除,会产生什么影响?

*如果我们要考虑约束,我们可能要考虑外键约束的影响——我们有一个client_ref列,在生产系统中,它可能是对clients表的外键引用。让我们创建这个表并添加外键约束。

*当我们使事情变得更困难时——有一个众所周知的特性将数组处理转换为“逐行”处理——触发器。如果我们向表中添加行级触发器,会产生什么效果?什么类型的触发器(在之前/之后、插入/更新/删除)有什么区别吗?

以下是一些结果-首先,主键约束的非唯一索引:

alter table t1 drop primary key;
alter table t1 add constraint t1_pk primary key(id)
deferrable initially immediate
using index nologging tablespace test_8k_assm_2
;
delete  from t1 where id <= 5e6;
5000000 rows deleted.
Name                                 Value
----                                 -----
sorts (rows)                     15,000,004

在这个例子中,Oracle将我的主键索引设置为非惟一,作为约束可延迟的副作用,但是即使约束不可延迟,并且您只是将索引创建为非惟一,其效果也是一样的。统计数据告诉我们,我们已经将优化应用于四个索引中的三个——快速检查一下v$segment_statistics,就会发现它是主键索引,没有进行特殊处理,它受到了超过500万个“db块更改”的影响。在这一点上,有必要快速检查一下,看看通过其他索引驱动是否会改变这种情况——但是不会,这是惟一约束与非惟一索引结合的副作用。

其次,当大表是“子表”时,引用完整性的影响:

create table t2 (
        client_id,
        client_name
) as
select
        distinct
                client_ref,
                rpad('x',100,'x')
from
        t1
;
alter table t2 add constraint t2_pk primary key(client_id);
alter table t1 modify client_ref not null;
alter table t1 add constraint t1_fk_t2 foreign key (client_ref) references t2(client_id);
5000000 rows deleted.
Name                                 Value
----                                 -----
sorts (rows)                    15,002,849

我们已经排序了大约1500万行,而通常我们需要排序2000万行.同样,我们可以检查v$segment_statistics来找出哪个索引遭受了500万的损失“db block changes”你可能不会对“外键”索引被逐行维护而感到惊讶-我们可能会猜测,这是某种先发制人的代码使得Oracle必须处理“外键锁定”威胁。 我们通过主键删除这个特定测试的后续操作是,考虑如果我们通过外键索引本身删除,或者甚至将约束修改为“on delete cascade”并删除一些父行,将会发生什么。通过client_ref在t1上驱动delete仍然优化了其他三个索引,但是当您试图利用“on delete cascade”机制时,这个技巧根本没有机会产生大规模的效果。在幕后你会发现这样的事情:

delete from "TEST_USER"."T1"
where
 "CLIENT_REF" = :1
call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        3      0.00       0.00          0          0          0           0
Execute   3000      5.23      15.37      69349       9238     428052       32510
Fetch        0      0.00       0.00          0          0          0           0
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total     3003      5.23      15.37      69349       9238     428052       32510
Rows (1st) Rows (avg) Rows (max)  Row Source Operation
---------- ---------- ----------  ---------------------------------------------------
     0          0          0  DELETE  T1 (cr=3 pr=22 pw=0 time=9672 us)
     7          8         11   INDEX RANGE SCAN T1_CLIENT (cr=3 pr=0 pw=0 time=125 us cost=3 size=594 card=22)(object id 150589)
This output the consequence of a bulk delete of 3,000 rows from t2 – because of the “on delete cascade”, the delete operated row by row on t2 and for each row Oracle executed a delete statement against t1.

这个输出是t2批量删除3000行的结果——由于“ on delete cascade ”,delete在t2上逐行操作,对于每一行Oracle都对t1执行一条delete语句。

从技术上讲,基于数组的优化是有效的,由于索引范围扫描,它给我们带来了一点好处,但是数据的分散性是如此之大,以至于每次调用几乎没有给我们带来任何好处。在某个阶段,我们将不得不进一步探索这种父/子的关系。

最后是触发器。众所周知,行级触发器可以将数组处理转换为单行处理——Oracle的索引维护优化也会发生同样的事情吗?

create or replace trigger t1_brd
before delete on t1
for each row
begin
    null;
end;
/
delete  from t1 where id <= 5e6;
5000000 rows deleted.
Name                                 Value
----                                 -----
sorts (rows)                         2,639

优化完全消失了。同样的事情也会发生在“为每一行删除后”触发器上,但是如果触发器是insert或update(行级)触发器,则不会发生这种情况。值得一提的是,索引优化也发生在索引列的值发生变化的更新上(请参阅本文),因此留给感兴趣的读者一个练习,看看哪些(如果有的话)触发器类型允许优化在数组更新后继续存在。

| 译者简介

汤健·沃趣科技数据库技术专家

沃趣科技数据库工程师,多年Oracle数据库从业经验,深入理解Oracle数据库结构体系,现主要参与公司一体机产品安装、测试、优化,并负责电信行业数据库以及系统运维。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

大数据量删除的思考(四)

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

MySQL 删除数据 批量删除(大量)数据

在删除数据的时候根据不同的场景使用不同的方法,比如说删除表中部分数据、删除表的结构、删除所有记录并重置自增ID、批量删除大量数据等,可以使用delete、truncate、drop等语句。 一、方法分类 二、具体方法 类型语句删除全部/部
2023-08-30

mysql 大表批量删除大量数据的实现方法

问题参考自:https://www.zhihu.com/question/440066129/answer/1685329456 ,mysql中,一张表里有3亿数据,未分表,其中一个字段是企业类型,企业类型是一般企业和个体户,个体户的数据量
2022-05-11

oracle怎么快速删除大量数据

要快速删除大量数据,可以使用Oracle的DELETE语句结合一些优化技巧来实现。以下是一些可以加快删除大量数据速度的方法:1. 使用TRUNCATE语句:TRUNCATE语句比DELETE语句更快,因为它不会将数据逐行删除,而是直接释放表
2023-08-31

oracle如何快速删除大量数据

要在Oracle中快速删除大量数据,可以尝试以下方法:1. 使用TRUNCATE语句:TRUNCATE语句可以快速删除表中的所有数据,而不是逐行删除。它比DELETE语句更高效,因为它不会生成事务日志,并且可以立即释放表空间。但是,请注意,
2023-10-08

oracle删除大量数据慢怎么解决

要提高Oracle删除大量数据的速度,可以考虑以下几个方面的优化:使用适当的删除语句:确保删除语句使用了合适的索引,避免全表扫描。可以通过分析表的使用情况和查询执行计划,确定是否需要创建新的索引或优化现有索引。批量删除:使用批量删除语句,如
oracle删除大量数据慢怎么解决
2024-04-09

redis怎么大批量删除缓存数据

要大批量删除Redis缓存数据,可以使用Redis的DEL命令来删除多个key。以下是一些方法:使用通配符删除:可以使用通配符来匹配多个key,然后一次性删除这些匹配的key。例如,可以使用如下命令来删除所有以"prefix:"开头的key
redis怎么大批量删除缓存数据
2024-04-09

mysql删除大量数据会不会锁表

MySQL在删除大量数据时会进行锁表操作,这可能会导致其他查询或写操作被阻塞,从而影响数据库的性能和吞吐量。具体来说,MySQL在执行删除操作时,默认会使用表级锁定(LOCK TABLES)来锁定整个表,直到删除操作完成。这意味着其他查询
2023-10-23

MongoDB中如何优雅地删除大量数据

删除大量数据,无论是在哪种数据库中,都是一个普遍性的需求。除了正常的业务需求,我们需要通过这种方式来为数据库“瘦身”。为什么要“瘦身”呢?表的数据量到达一定量级后,数据量越大,表的查询性能会越差。毕竟数据量越大,B+树的层级会越高,需要的IO也会越多。表的数据
MongoDB中如何优雅地删除大量数据
2017-11-11

mysql中删除数据的四种方法小结

目录写在前面 方法介绍1. DELETE语句示例: 2. DROP TABLE语句:3. TRUNCATE TABLE示例:4. 使用外键约束:示例: 方法优缺点1. DELETE语句:2. TRUNCATE TABLE语句:3. DR
2023-10-11

大数据时代的重复数据删除技术

编程学习网:重复数据删除在几年前是一个独立的功能,主要用于企业备份和归档部门的存储系统。如如今,重复数据删除在云端网关找到了新的用途,为即将进入阵列或虚拟磁带库的数据过滤掉没有用处的数据。重复数据删除技术已经成为一种统计算系统预先集成的功能,而企业对于这项技术的有效使用成为一种需求。
大数据时代的重复数据删除技术
2024-04-23

编程热搜

目录