• 一次delete速度异常慢的处理过程


    step1,一个简单的联系人表 
    Java代码  收藏代码
    1. CREATE TABLE `contact784` (  
    2.     `cid` bigint AUTO_INCREMENT NOT NULL,  
    3.     `uid` bigint NOT NULL,  
    4.     `email` varchar(128) NOT NULL,  
    5.     `name` varchar(64) NOT NULL,  
    6.     `mobile` varchar(16)  NULL,  
    7.     `atime` timestamp NULL,  
    8.     `type` enum('BLACK','WHITE','NORMAL') NOT NULl default 'NORMAL',  
    9.     `info` text NULL,  
    10.     `memo` varchar(1024)  NULL,  
    11.      PRIMARY key(`cid`)  
    12. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT = 100;  
    13. ALTER TABLE `contact784` ADD UNIQUE INDEX uniq_uid_email(`uid`,`email`);  


    step2,插入了100W数据: 
    Java代码  收藏代码
    1. # -*- coding: utf-8 -*-    
    2. #@author python.han@gmail.com  
    3.   
    4. import MySQLdb  
    5. import random  
    6. import string  
    7. import threading  
    8. import time  
    9.   
    10. domains = ['org','com.cn','qq.com','yahoo.com','163.com','com','cn','sina.cn','sina.com']  
    11. host = "localhost"  
    12. user = "xx"  
    13. pwd = "xx"  
    14. db = "t3"  
    15.   
    16. def getRandomValue():  
    17.   email = ""  
    18.   s = ""  
    19.   for x in range(random.randint(1,10)):  
    20.     s += random.choice(string.letters)  
    21.   b = list(s)  
    22.   domain = ''.join(b)+"."+random.choice(domains)  
    23.   email = s+"@"+domain  
    24.   return email,s  
    25.   
    26.   
    27. def insert(count):  
    28.   conn=MySQLdb.connect(host=host,user=user,passwd=pwd,db=db)   
    29.   cursor=conn.cursor()  
    30.   for cid in xrange(count):  
    31.     uid = random.randint(1000000000,9999999999)  
    32.     email,name = getRandomValue()  
    33.     sql = "insert into contact784(uid,email,name) values (%d,'%s', '%s')" %(uid,email,name)  
    34.     n=cursor.execute(sql)   
    35.   cursor.close()  
    36.   conn.commit ()  
    37.   conn.close()  
    38.   
    39.   
    40. if __name__=='__main__':  
    41.   
    42.   start = time.clock()  
    43.   for i in range(100):  
    44.     worker = threading.Thread(target = insert(10000))  
    45.     worker.start()  
    46.   end = time.clock()  
    47.   print "elsaped:%s" %(end-start)  


    step3,要重新单线程插入,需要把数据清空. 
    因为python多线程由于GIL的关系,实际上上面的100个线程只产生了一个连接,需要测试一下纯单线程插入是不是要快些:) 

    执行:delete from contact784 
    半小时没有执行完毕! 

    诊断方式: 
    1,iostat ,top等查看磁盘io很大 
    2,inotifywatch发现io的事件非常多 

    原因:在大表上使用delete from 清空一个表是非常慢的。因为InnoDB必须处理表中的每一行,根据InnoDB的事务设计原则,首先需要把“删除动作”写入“事务日志”,然后写入实际的表。所以,清空大表的时候,最好直接drop table然后重建。 
    注: 
    在delete from 执行的过程中: 
    用:select count(*) from contact784;发现表的数据量一直是100行 
    用:explain select count(*) from contact784;可以发现数量一直在减少,显示当前 

    784是是因为前面这个文章的原因“ 
    http://hanyh.iteye.com/blog/431323 
     
     
     
     
    我从oracle undo的角度来回答哈:
    delete是个极其昂贵的操作哦,它会产生大量的undo数据(最多的),你每删一次oracle都要记录一次。
    如果从undo角度来看的话,可以优化的就是控制事务的长度,即用:commit。
     
     
     
     

    一次delete速度异常慢的处理过程

    转自:http://space.itpub.net/10710960/viewspace-610982

    一次小数据量删除,但花费2个小时还没完成的问题

    delete from TOPBOX_COURSEWARE where id like '760%';
    花费非常长的时间,topbox_courseware表大概2w数据,要删除的也就2500条数据。
    问题原因:
    由于TOPBOX_COURSEWARE表与多个表有外键关联,而且关联的表中有2张千万级别的大表。
    通过v$session_wait,v$session表

    select * from v$session_wait a,v$session b
    where b.sid=a.sid
    and a.event not like 'SQL*Net%';

    发现该session的event是db file scattered read。
    这个事件一般是表示法伤了全表扫描相关的等待。通常意味着全表扫描过多,或者I/O能力不足,或是I/O争用造成的。

    解决方法:
    1.通过dba_constraints表找到topbox_courseware表对应的约束
    select * from dba_constraints where constraint_type='R' and wner='TOPBOX' and r_constraint_name='PK_TOPBOX_COURSEWARE'
    得到两个外键约束名
    FK_TOPBOX_COURSCO_REF_COUR
    FK_TOPBOX_CSTUDY_REF_COUSE

    2.通过命令将这2个约束disable
    alter table topbox_coursescore disable constraint fk_topbox_coursco_ref_cour;
    alter table topbox_coursestudy disable constraint fk_topbox_cstudy_ref_couse;

    通过上面的处理delete只需要不到1秒的时间

    3.将约束重新激活
    由于topbox_coursescore,topbox_coursestudy是千万级的大表,如果直接enable而不加其他参数,启用约束后,oracle会对表中数据
    逐条检查,所以速度会非常慢。而且已经插入的数据没有脏数据,所以为了避免不必要的工作,就要使用novalidate
    alter table topbox_coursescore enable novalidate constraint fk_topbox_coursco_ref_cour;
    alter table topbox_coursestudy enable novalidate constraint fk_topbox_cstudy_ref_couse;
  • 相关阅读:
    easyui 后台系统引入富文本编辑器的使用
    easyui datagrid 表格动态隐藏部分列的展示
    java ArrayList源码分析(转载)
    propertychange方法
    CSS margin-top 属性
    easyui-textbox input输入框的一种取值方式
    jquery next()方法
    jquery children()方法
    一段简单的表格样式
    常用的排序算法的时间复杂度和空间复杂度
  • 原文地址:https://www.cnblogs.com/timssd/p/9794435.html
Copyright © 2020-2023  润新知