oracle 删除主键_大数据量删除的思考 4

b104099f14869fe88609a884de4282f2.png

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

出品  沃趣科技

c2ebd5e0df45ef286e12828ad9cb3568.png

575d98c78cda1fd61fc5b7fc6926e9e8.gif在本系列的前一期文章中,我制作了一些图,突出显示了按表扫描执行大量删除操作和按索引范围扫描执行大量删除之间的主要区别。根据所涉及的数据模式,选择正确的策略可能对随机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 /*+ index_desc(t1 t1_pk) */ 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 /*+ index(t1 t1_dt_open) */ 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 /*+ index(t1 t1_pk) */ 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 /*+ index(t1 t1_pk) */ from t1 where id <= 5e6;

5000000 rows deleted.

Name                                 Value
----                                 -----
sorts (rows)                         2,639

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

| 译者简介

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

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

相关链接

MySQL 一个让你怀疑人生的hang死现象

MySQL 执行DDL语句 hang住了怎么办?

MySQL行级别并行复制能并行应用多少个binlog group?

binlog server还是不可靠吗?

MySQL binlog基于时间点恢复数据失败是什么鬼?

开源监控系统Prometheus的前世今生

prometheus监控多个MySQL实例

MySQL问题两则

Kubernetes scheduler学习笔记

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

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

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

统计信息记录表|全方位认识 mysql 系统库

数据库对象信息记录表|全方位认识 mysql 系统库

访问权限控制系统|全方位认识 mysql 系统库

权限系统表 | 全方位认识 mysql 系统库

Oracle RAC Cache Fusion 系列十四:Oracle RAC CR Server Part One

Oracle RAC Cache Fusion 系列十三:PCM资源访问

Oracle RAC Cache Fusion 系列十二:Oracle RAC Enqueues And Lock Part 3

Oracle RAC Cache Fusion 系列十一:Oracle RAC Enqueues And Lock Part 2

Oracle RAC Cache Fusion 系列十:Oracle RAC Enqueues And Lock Part 1

928b669ac987bcd11537db46df571c1a.png

更多干货,欢迎来撩~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/396601.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

redis 持久化 + 主从复制+ 集群

2019独角兽企业重金招聘Python工程师标准>>> 一、 Linux 下的 Redis 安装 && 启动 && 关闭 && 卸载 http://blog.csdn.net/zgf19930504/article/details/51850594 注&#xff1a;设置 redis.conf bind***.***.*.(127.0.0.1) redis启动&…

怎么运行c语言_C语言 原来是这样调用硬件的

大家都知道我们可以使用C语言写一段程序来控制硬件工作&#xff0c;但你知道其工作原理吗&#xff1f;网友北极C语言在实际运行中&#xff0c;都是以汇编指令的方式运行的&#xff0c;由编译器把C语言编译成汇编指令&#xff0c;CPU直接执行汇编指令。所以这个问题就变成&#…

四、元祖、字典

一、元祖(tuple)&#xff1a;tu(11,"hello",(0,1),[11,"111"],33,) 元祖的特点&#xff1a;元祖中一级元素不可被修改&#xff0c;不能被增加或删除&#xff0c;多级元素可以被修改&#xff0c;一般写元祖的时候&#xff0c;推荐在后面添加逗号“&#xff…

PHP编程效率的20个要点

用单引号代替双引号来包含字符串&#xff0c;这样做会更快一些。因为PHP会在双引号包围的字符串中搜寻变量&#xff0c;单引号则 不会&#xff0c;注意&#xff1a;只有echo能这么做&#xff0c;它是一种可以把多个字符串当作参数的“函数”(译注&#xff1a;PHP手册中说echo是…

ubuntu运行python ide_打造vim中的python IDE

首先先介绍几个常用的插件&#xff1a;1&#xff0c;ctags和taglist&#xff0c;这个大家估计都很常用&#xff0c;在ubuntu下只要安装exuberant-ctags即可啦&#xff0c;另外tagbar支持面向对象语言的展示" toggle Tagbar displaymap :TagbarToggle" autofocus on T…

更新和插入的并发问题_mysql经典面试题:如何读写分离?主从原理是啥?同步的延时问题...

面试题你有没有做 MySQL 读写分离&#xff1f;如何实现 MySQL 的读写分离&#xff1f;MySQL 主从复制原理的是啥&#xff1f;如何解决 MySQL 主从同步的延时问题&#xff1f;考点分析高并发这个阶段&#xff0c;肯定是需要做读写分离的&#xff0c;啥意思&#xff1f;因为实际上…

php实现一个简单的四则运算计算器

php实现一个简单的四则运算计算器&#xff08;还不支持括号的优先级&#xff09;。利用栈这种数据结构来计算表达式很赞。 这里可以使用栈的结构&#xff0c;由于php的数组“天然”就有栈的特性&#xff0c;这里直接就利用了数组。当然可以使用栈结构写&#xff0c;道理一样的。…

Tcp与Ip协议的客户端和服务器编程

Tcp与Ip协议的客户端和服务器编程 本文就TCP和Ip协议的客户端和服务器分别进行编程&#xff0c;实现了客户端和服务端进行通信的功能&#xff0c;服务端对多个客户端进行监听&#xff0c;并能与多个客户端通信。 服务器端代码如下&#xff1a; using System; using System.Coll…

maven建立webapp项目时显示Cannot change version of project facet Dynamic web module to 2.5

为什么80%的码农都做不了架构师&#xff1f;>>> 网上查了很多东西都没啥用&#xff0c;其实直接把这段代码加到web.xml头部&#xff0c;自然就不报错了 <?xml version"1.0" encoding"UTF-8"?> <web-app xmlns:xsi"http://www.…

python数据结构算法 北京大学_北京大学公开课《数据结构与算法Python版》

之前我分享过一个数据结构与算法的课程&#xff0c;很多小伙伴私信我问有没有Python版。看了一些公开课后&#xff0c;今天特向大家推荐北京大学的这门课程&#xff1a;《数据结构与算法Python版》。课程概述很多同学想要转行机器学习&#xff0c;也确实掌握了一些机器学习模型…

20道C#练习题(一)1——10题

1.输入三个整数&#xff0c;xyz&#xff0c;最终以从小到大的方式输出。利用if嵌套。 Console.Write("请输入x"); double x double.Parse(Console.ReadLine()); Console.Write("请输入y"); double y double.Parse(Console.ReadLine()); Console.Write(&q…

fd 句柄_linux文件描述符fd(windows下的句柄)

在Linux系统中一切皆可以看成是文件&#xff0c;文件又可分为&#xff1a;普通文件、目录文件、链接文件和设备文件fd&#xff1a;file descriptor文件描述符0,1,2分别给了标准输入、标准输出和错误输出。ls -l /proc/pid/fd可以查看某个进程所使用的fd用lsof可以查看比如&…

Python——三级菜单

#三级菜单函数 menu {北京&#xff1a;&#xff5b;海淀&#xff1a;&#xff5b;五道口&#xff1a;&#xff5b;&#xff5d;中关村&#xff1a;&#xff5b;&#xff5d;上帝&#xff1a;&#xff5b;&#xff5d;&#xff5d;昌平&#xff1a;&#xff5b;&#xff5d;朝阳…

HTTPS 原理解析

http://www.cnblogs.com/zery/p/5164795.html 一 前言 在说HTTPS之前先说说什么是HTTP&#xff0c;HTTP就是我们平时浏览网页时候使用的一种协议。HTTP协议传输的数据都是未加密的&#xff0c;也就是明文的&#xff0c;因此使用HTTP协议传输隐私信息非常不安全。为了保证这些隐…

python 函数参数注解_python-如何使用函数注释来验证函数调用类...

我最近才发现有一种叫做函数注释的东西,但是我不太确定如何使用它.这是我到目前为止的内容&#xff1a;def check_type(f):def decorated(*args, **kwargs):counter0for arg, type in zip(args, f.__annotations__.items()):if not isinstance(arg, type[1]):msg Not the vali…

SQL Server Replication 中关于视图的点滴

在服务器A数据库TEST新建了一个本地发布&#xff08;Local Publications&#xff09;RPL_GES_MIS_TEST,在服务器B数据库RPL_TEST上创建了一个本地订阅&#xff08;Local Subscriptions&#xff09;&#xff0c;它订阅了了这个发布RPL_GES_MIS_TEST.如下截图所示&#xff0c;本地…

kbmmw 5.0 中的REST 服务

目前关于REST 服务的话题越来越热&#xff0c;kbmmw 在5.0 里面开始支持rest。今天我就试一下kbmmw 的 rest 服务。闲话少说&#xff0c;开始。 老规矩&#xff0c;放上两个kbmMWServer1和 kbmMWHTTPSysServerTransport1两个控件。 设置kbmMWHTTPSysServerTransport1的server 属…

php7 匿名继承类_PHP7匿名类的用法示例

本文实例讲述了PHP7匿名类的用法。分享给大家供大家参考&#xff0c;具体如下&#xff1a;/*** Created by PhpStorm.* User: Itboot* Date: 2019/1/17* Time: 18:15*/class An{private $num;protected $age 15;public function __construct() {$this->num 1;}protected f…

python中不需要函数重载的原因

函数重载主要是为了解决两个问题&#xff1a; 1.可变参数类型 2.可变参数个数 并且函数重载一个基本的设计原则是&#xff0c;仅仅当两个函数除了参数类型和参数个数不同以外&#xff0c;其功能是完全相同的&#xff0c;此时才使用函数重载&#xff0c;如果两个函数的功能其实不…

多租户saas 架构_[译/注] Force.com 多租户互联网应用开发平台的设计

原文地址 http://cloud.pubs.dbs.uni-leipzig.de/sites/cloud.pubs.dbs.uni-leipzig.de/files/p889-weissman-1.pdf译注&#xff1a;原文发表于 ACM&#xff0c;2009年6月作者Craig D Weissman, CTO, Salesforce.comSteve Bobrowski, Technical Marketing Consultant, Salesfor…