楼主: homeworld80

大数据量删除时delete的表现

[复制链接]
论坛徽章:
9607
土豪章
日期:2013-12-31 14:11:39土豪章
日期:2013-12-31 14:11:39阿森纳
日期:2013-06-03 17:00:31阿森纳
日期:2013-10-11 09:27:58法拉利
日期:2013-12-27 15:20:30林肯
日期:2013-12-27 15:19:09法拉利
日期:2013-12-27 15:20:30法拉利
日期:2013-12-27 15:20:30法拉利
日期:2013-12-27 15:20:30法拉利
日期:2013-12-27 15:20:30
11#
发表于 2010-4-10 13:36 | 只看该作者
值得研究一下

使用道具 举报

回复
论坛徽章:
87
2015年新春福章
日期:2015-03-06 11:58:182010广州亚运会纪念徽章:轮滑
日期:2010-09-23 17:19:212010年世界杯参赛球队:乌拉圭
日期:2010-07-14 17:54:242010年世界杯参赛球队:美国
日期:2010-06-30 13:13:582010年世界杯参赛球队:墨西哥
日期:2010-06-25 12:49:452010年世界杯参赛球队:墨西哥
日期:2010-04-05 10:23:502010新春纪念徽章
日期:2010-03-01 11:06:232010新春纪念徽章
日期:2010-01-04 08:33:08生肖徽章2007版:龙
日期:2009-11-12 16:31:13参与WIN7挑战赛纪念
日期:2009-11-09 11:50:09
12#
发表于 2010-4-10 15:29 | 只看该作者
Good Job!

使用道具 举报

回复
论坛徽章:
18
ITPUB元老
日期:2008-12-17 09:07:172012新春纪念徽章
日期:2012-01-04 11:51:22ITPUB十周年纪念徽章
日期:2011-11-01 16:21:152011新春纪念徽章
日期:2011-02-18 11:43:32季节之章:秋
日期:2011-01-23 18:06:29生肖徽章2007版:兔
日期:2011-01-20 12:58:492011新春纪念徽章
日期:2011-01-04 10:24:582010新春纪念徽章
日期:2010-03-01 11:06:12设计板块每日发贴之星
日期:2010-01-20 01:01:06设计板块每日发贴之星
日期:2010-01-15 01:01:08
13#
发表于 2010-4-10 21:35 | 只看该作者
值得赞赏。

使用道具 举报

回复
论坛徽章:
1
ITPUB学员
日期:2010-05-09 21:25:44
14#
发表于 2010-4-11 19:14 | 只看该作者
关注学习下

使用道具 举报

回复
论坛徽章:
1
2010新春纪念徽章
日期:2010-03-01 11:08:28
15#
发表于 2010-4-13 09:47 | 只看该作者
高手啊,学习下

使用道具 举报

回复
论坛徽章:
0
16#
发表于 2010-4-17 13:38 | 只看该作者
很不明白,为什么会这样呢?

使用道具 举报

回复
论坛徽章:
0
17#
发表于 2010-4-30 23:33 | 只看该作者
Day Day Up

使用道具 举报

回复
论坛徽章:
32
奥运会纪念徽章:摔跤
日期:2012-08-23 11:03:05青年奥林匹克运动会-击剑
日期:2014-09-19 10:58:152014年世界杯参赛球队:巴西
日期:2014-07-07 12:19:232014年世界杯参赛球队: 瑞士
日期:2014-05-19 12:18:36马上有钱
日期:2014-04-08 12:12:232014年新春福章
日期:2014-04-04 14:20:47马上有钱
日期:2014-02-18 16:43:092014年新春福章
日期:2014-02-18 16:43:09红旗
日期:2014-02-14 15:15:55优秀写手
日期:2013-12-18 09:29:16
18#
发表于 2010-5-1 10:55 | 只看该作者
OO说的很清楚,不过我也没有试验。

使用道具 举报

回复
论坛徽章:
0
19#
发表于 2010-5-16 18:43 | 只看该作者
看到这个帖子,忽然想到一个数据维护顺序的问题,总的来说,我觉得可能存在三种维护顺序:
1.先维护表数据,再维护索引数据;
2.先维护索引数据,再维护表数据;
3.前两者的结合。

对于
2、循环删除(使用索引):
SQL> begin
  2  for v in (select name from testp) loop
  3  delete from testc where name = v.name;
  4  end loop;
  5  commit;
  6  end;
  7  /

如果是第二种方案的话,这里先使用索引找到name=:1的索引项,一项一项的删除索引条目的同时通过rowid找到表数据项,删除这些表数据项,这样当clustering_factor很大的时候,表数据维护的逻辑IO可能会很大,因为对于同一个name来说,同一个数据块可能会被多次读取(一个索引的叶块上,会按照rowid排序吗?如果会按照rowid排序的话,对于同一个name来说,同一个数据块也只会被读取一次,但我觉得应该不是按照rowid排序的.是吗?望高人给出见解),但可以使用表预取技术,先取得rowid list,排序后,再去维护表数据,这样对于同一个name来说,同一个数据块只会被读取一次。

对于
1、直接删除:
SQL> delete from testc;

如果是第一种方案的话,根据表数据项如何找到对应的索引项呢?
索引条目里记录着rowid,可以很容易的找到对应的表数据项,
但反过来,一个数据项对应的索引项该如何找到呢?
比如说删除的这行数据name='z'  rowid='xxxxxxxx';
把name='z'作为一个access predicateslai定位索引项目,然后把rowid='xxxxxxxx'作为一个filter predicates来定位最终要删除的索引条目,但感觉这样做效率也太低了吧?!


当然,上面说得有点儿乱,不知道大家怎么看这个问题.

使用道具 举报

回复
论坛徽章:
0
20#
发表于 2010-5-16 22:43 | 只看该作者
delete数据行的时候,是如何定位对应的索引条目的呢?
create table zsj_obj2 as select * from dba_objects;
insert into zsj_obj2 select * from zsj_obj2; 多次执行
commit;
select count(1) from zsj_obj2;                                                                                
  COUNT(1)
----------
    808544

update zsj_obj2 set object_id=rownum,object_name='ZSJ_TEST';
COMMIT;
实际上只有一个object_name
CREATE INDEX IND_ZSJ_OBJ2_ID ON ZSJ_OBJ2(OBJECT_ID);
CREATE INDEX IND_ZSJ_OBJ2_NAME ON ZSJ_OBJ2(OBJECT_NAME);
exec dbms_stats.gather_table_stats(user,'ZSJ_OBJ2',CASCADE=>TRUE,METHOD_OPT=>'FOR ALL INDEXED COLUMNS SIZE 1');
select BLEVEL,LEAF_BLOCKS from user_indexes where index_name='IND_ZSJ_OBJ2_NAME';                             
    BLEVEL LEAF_BLOCKS
---------- -----------
         2        2253
如果像我猜想的那样,删除一个数据行的时候,根据这个数据行的索引列值来access索引并根据rowid来filter并最终确定要删除的索引条目的话,那么定位叶块链表上第一个叶块,最后一个叶块和中间的叶块上的索引条目的逻辑IO一定是不同的(因为只有一个object_name,根据rowid来filter索引条目的话,第一个叶块,最后一个叶块,中间叶块的逻辑IO一定是不同的),可下面的实验结果却是完全相同的.

variable v_object_id number;
exec :v_object_id:=1;
set autotrace on;
delete from zsj_obj2 where object_id=:v_object_id;
1 row deleted.
-------------------------------------------------------------------------------------
| Id  | Operation         | Name            | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------
|   0 | DELETE STATEMENT  |                 |     1 |    14 |     3   (0)| 00:00:01 |
|   1 |  DELETE           | ZSJ_OBJ2        |       |       |            |          |
|*  2 |   INDEX RANGE SCAN| IND_ZSJ_OBJ2_ID |     1 |    14 |     3   (0)| 00:00:01 |
-------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("OBJECT_ID"=TO_NUMBER(:V_OBJECT_ID))

Statistics
----------------------------------------------------------
          1  recursive calls
          9  db block gets
          6  consistent gets
          1  rows processed

exec :v_object_id:=808540;
delete from zsj_obj2 where object_id=:v_object_id;
                                                        
1 row deleted.
-------------------------------------------------------------------------------------
| Id  | Operation         | Name            | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------
|   0 | DELETE STATEMENT  |                 |     1 |    14 |     3   (0)| 00:00:01 |
|   1 |  DELETE           | ZSJ_OBJ2        |       |       |            |          |
|*  2 |   INDEX RANGE SCAN| IND_ZSJ_OBJ2_ID |     1 |    14 |     3   (0)| 00:00:01 |
-------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("OBJECT_ID"=TO_NUMBER(:V_OBJECT_ID))

Statistics
----------------------------------------------------------
          0  recursive calls
          9  db block gets
          6  consistent gets
          1  rows processed

exec :v_object_id:=400000;
delete from zsj_obj2 where object_id=:v_object_id;
1 row deleted.
-------------------------------------------------------------------------------------
| Id  | Operation         | Name            | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------
|   0 | DELETE STATEMENT  |                 |     1 |    14 |     3   (0)| 00:00:01 |
|   1 |  DELETE           | ZSJ_OBJ2        |       |       |            |          |
|*  2 |   INDEX RANGE SCAN| IND_ZSJ_OBJ2_ID |     1 |    14 |     3   (0)| 00:00:01 |
-------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("OBJECT_ID"=TO_NUMBER(:V_OBJECT_ID))

Statistics
----------------------------------------------------------
          0  recursive calls
          9  db block gets
          6  consistent gets
          1  rows processed

exec :v_object_id:=100000;                                                                                    
delete from zsj_obj2 where object_id=:v_object_id;                                                            
1 row deleted.
-------------------------------------------------------------------------------------
| Id  | Operation         | Name            | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------
|   0 | DELETE STATEMENT  |                 |     1 |    14 |     3   (0)| 00:00:01 |
|   1 |  DELETE           | ZSJ_OBJ2        |       |       |            |          |
|*  2 |   INDEX RANGE SCAN| IND_ZSJ_OBJ2_ID |     1 |    14 |     3   (0)| 00:00:01 |
-------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("OBJECT_ID"=TO_NUMBER(:V_OBJECT_ID))

Statistics
----------------------------------------------------------
          0  recursive calls
          9  db block gets
          6  consistent gets
          1  rows processed
  
通过dump索引结构,可以知道在IND_ZSJ_OBJ2_NAME索引上,1确实是叶块链表中第一个叶块上的条目,808540确实是叶块链表中最后一个叶块上的条目.
其实,这也是我早就预料到的结果,oracle怎么可能那样去定位一个已经存在的数据行对应的索引条目的位置呢?那么oracle又是如何定位的呢?是在叶块上添加还是在数据块上添加了什么结构变量而后能够迅速定位了呢?

使用道具 举报

回复

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

TOP技术积分榜 社区积分榜 徽章 团队 统计 知识索引树 积分竞拍 文本模式 帮助
  ITPUB首页 | ITPUB论坛 | 数据库技术 | 企业信息化 | 开发技术 | 微软技术 | 软件工程与项目管理 | IBM技术园地 | 行业纵向讨论 | IT招聘 | IT文档
  ChinaUnix | ChinaUnix博客 | ChinaUnix论坛
CopyRight 1999-2011 itpub.net All Right Reserved. 北京盛拓优讯信息技术有限公司版权所有 联系我们 未成年人举报专区 
京ICP备16024965号-8  北京市公安局海淀分局网监中心备案编号:11010802021510 广播电视节目制作经营许可证:编号(京)字第1149号
  
快速回复 返回顶部 返回列表