问题是这样的,我有一个大表(就十几亿数据吧),表多个字段都建有索引,现在需要再向该表插入数据(也就1000万以下吧),有哪些方法再不删除索引的情况下,较快的完成这个插入过程。
参与者都给分,不够我再加,谢谢!

解决方案 »

  1.   


    1,写个脚本,如果是从别的表导入的话,建议用insert tb1() select c1,c2,...... from tb22,如果是从excel文档里面导入或者从别sqlserver的数据库导入的话,建议用专门的工具来做。3,索引的影响是无法消除的,除非这些索引你不用了,你可以删除索引或者使索引失效都可以的。
      

  2.   

    查询出140万数据耗时久吗?还有数据库是归档模式吧?你只有先alter table t nologging,再用insert append才会有效大量减少redo,还可以考虑用并行,不过要注意对业务的影响。
      

  3.   


    1. 取消归档 这个不用说了。
    2. 使用insert into t select from othertable.(这种方式不会产生重做日志)
    3. append hint 减少磁头位移
    不过这里的方法仅仅只是从单纯从插入数据这个方面出发的,index的影响无法去掉。所以最好的方法是drop index再配合上面的方法
    ==================================================================
    Inthirties关注Oracle数据库 维护 优化,安全,备份,恢复,迁移,故障处理如果你需要帮助或想和我一起学习的请联系
    联系方式QQ:370140387
    QQ群:  85837884(注明:数据库)
    电子邮件:[email protected]
    网站: http://www.inthirties.com
      

  4.   

    还是用sqlloader这样的工具吧,或者自己写一个程序调用sqlloader都是可以的。速度应该会快很多
      

  5.   


    用sqlloader向有索引的表导数据速度比没索引的慢很多,还不知道到能不能用并行和直接加载的方式向带索引的表加载数据。
      

  6.   


    这样的情况只能具体分析:
    1) 13亿的数据,我想你一定分区了吧. 新加入的数据是否可以单独成为一个PARTITION, 如果没有,也可以依照某种条件分区,
    把新加入的数据作为一个新的分区.
    2)通过 exchange partition 的方式把数据出一个TABLE转入另外一个PARTITION TABLE. 局部索引的方式来降低导入的性能影响.
    操作方式参考下述链接:
    http://space.itpub.net/1698901/viewspace-416205谢谢!
      

  7.   

    直接路径插入(insert /*+append*/) 必须是表和所有它的索引都有nologging属性才有效。
    有时候在插入慢,是因为session没有足够的内存可以分配,可以用如下sql监控:
       SELECT * FROM v$sesstat a,v$statname b WHERE a.STATISTIC#=b.STATISTIC#
       AND NAME LIKE '%memory%'  AND sid=<sid号>
    如果发现瓶颈在内存,可调整相关参数
    exchange partition是可行的,但是可能会产生索引失效问题。
    如果该表的不同分区的数据分布于不同磁盘,或者采用了磁盘阵列(例如raid0+1),那么可以考虑使用并行插入
      

  8.   

    parallel dml+   range_partition_hashpartition,
    充分利用partition的并行特性,并减少在段头的竞争.当然,IO也应该要打散的.采用直接路径加载,不过会造成你的段比普通方式会大一些,但是速度会快非常多.
      

  9.   


    物理内存是16G的,如何将这些内存都分给oracle呢?
      

  10.   

    不过,可别有bitmap index,这样的话会造成enqueue.否则并行是没有任何问题的,当然了,如果有unique index的话,也要注意有冲突而产生enqueue.
      

  11.   

    分批次insert  这样应该会好一点哦
      

  12.   

    16G内存,考虑增大sga_target到8G-10G
    alter system set sga_target=8192M scope=both sid=your instance_name
      

  13.   


    禁用索引的话会影响应用,因为客户没有专门的DBA,所以所有的事情都要我们设计好。
      

  14.   


    Enqueue 队列是一种锁,保护一些共享资源,防止并发的DML操作。队列采用FIFO策略,注意latch并不是采用的FIFO机制。比较常见的有3种类型的队列:ST队列,HW队列,TX4队列。
    ST Enqueue的等待主要是在字典管理的表空间中进行空间管理和分配时产生的。解决方法:1)将字典管理的表空间改为本地管理模式 2)预先分配分区或者将有问题的字典管理的表空间的next extent设置大一些。
    HW Enqueue是用于segment的HWM的。当出现这种等待的时候,可以通过手工分配etents来解决。
    TX4 Enqueue等待是最常见的等待情况。通常有3种情况会造成这种类型的等待:1)唯一索引中的重复索引。解决方法:commit或者rollback以释放队列。 2)对同一个位图索引段(bitmap index fragment)有多个update,因为一个bitmap index fragment可能包含了多个rowid,所以当多个用户更新时,可能一个用户会锁定该段,从而造成等待。解决方法同上。3)有多个用户同时对一个数据块作update,当然这些DML操作可能是针对这个数据块的不同的行,如果此时没有空闲的ITL槽,就会产生一个block-level锁。解决方法:增大表的initrans值使创建更多的ITL槽;或者增大表的pctfree值,这样oracle可以根据需要在pctfree的空间创建更多的ITL槽;使用smaller block size,这样每个块中包含行就比较少,可以减小冲突发生的机会。
      

  15.   


    这个方案基本是最合适的。lz说分区将在下一阶段进行,那么我建议你们考虑把这个工作提到前面来做,
    因为非分区表无法直接变成分区表,这中间少不了要新建分区表--移动数据--删除原表的过程,
    所以现在要导入的数据不如直接导入到分区表中,然后考虑如何再online的方式下逐步把数据移动到分区表中
      

  16.   


    现在该的话要改前台应用,成本太高了,不知sqlloader能不能向分区表加载数据。用sqlloader加载数据还是相当快的。
      

  17.   

    sqlldr可以向分区表中加载数据
    几个注意点:
    1、先把bitmap index摘掉
    2、如果可能的话,先检查一下要加载的数据是否能满足unique index
       我有次load数据的时候,因为数据中存在pk重复,unique index rebuild到一半报错开始回滚,这一回滚就滚了4个小时
    3、直接路径加载,具体参数先找PC测试一下
    给你篇参考
    http://www.oracle.com/technology/global/cn/pub/notes/technote_loader_path.html我以前的一次sqlldr实施时间给你参考下
    record_count    datafile_size    use_time
       1亿              23GB           0:25:18
       1.5亿            36GB           0:39:49
       3.1亿            95GB           2:04:04direct=y
    columnarrayrows=100000  
      

  18.   


    我使用sqlldr实施时,导入未分区、不带索引的表时每个小时10~20G左右的速度,可能是没设置好吧。
      

  19.   


    topas + sar看看磁盘busy,还有os的io cache按18G/H计算,相当于5M/s,PC的话不错了,服务器的话,稍微差点
      

  20.   

    不要迷信sqlldr,以前我这边也有N多同事认为sqlldr比自己写程序导入要快
    实际真相是因为很多人用sqlldr的时候不是直接导入生产用的表,而是导入一个临时表,临时表中无索引,数据量小
    所以导入速度快
    上次做过测试,相同环境,导入同样数据,用sqlldr和自己用pro*c写的程序比较,事实证明sqlldr还要慢些。
      

  21.   


    sqlldr功能还是挺强大的,自己写的话,能实现的肯定很有限。
      

  22.   

    我刚测试了一下,100万数据插入到已有1亿数据的带索引的表中:
    sqlldr向有索引的表加载数据,direct = true时的速度跟直接insert/*append*/ 的速度差不多,如果direct=false的话速度超慢。
      

  23.   

    使用sqlldr向有索引的表加载数据不能启用并行模式
      

  24.   


    跟是否是生产库没关系,但你把sqlldr的长处(direct-path insert)全都没发挥出来,这个可不就跟insert差不多么
    让一个高中生和一个初中生一起算小学数学题,谁算得快还真不一定的
      

  25.   


    所以才建议你先把表分区的
    不过既然你不能停应用,那也无所谓的,不然load数据的时候,大量的io会让前台应用趴窝的,
    就慢慢load吧,呵呵
      

  26.   

    什么表这么大?如果是流水帐数据,应该建年表、或月表。然后通过 where 语句里的时间条件判断出表名进行操作。
      

  27.   

    总结:
    1. 分区,减少每次处理的数据量 
      1)新加入的数据单独成为一个PARTITION. 
      2)通过 exchange partition 的方式把数据出一个TABLE转入另外一个PARTITION TABLE. 局部索引的方式来降低导入的性能影响. 2. 切成几个小数据量,再插入,多次commit
    3. 取消归档 
    4. 使用insert into t select from othertable.(这种方式不会产生重做日志) 
    5. append hint 减少磁头位移 
    6.并行
    7.sqlldr向分区表中加载数据 
      几个注意点: 
       1)先把bitmap index摘掉 
       2)如果可能的话,先检查一下要加载的数据是否能满足unique index 
      我有次load数据的时候,因为数据中存在pk重复,unique index rebuild到一半报错开始回滚,这一回滚就滚了4个小时 
       3)直接路径加载,具体参数先找PC测试一下
    8.自己写pro*c程序
    9.凌晨业务量最少的时候做这种操作
    10.扩大缓冲区,alter system set sga_target=8192M scope=both sid=your instance_name
    11.临时禁用索引
      

  28.   

    1. 取消归档
    2. 使用insert into t select from othertable.(
    3. append hint 减少磁头位移 
      

  29.   

    实际方案的话我准备先尝试下以下几点
    1、分区
    2、sqlldr向分区表中加载数据
    3、 取消归档
    4、凌晨业务量最少的时候做这种操作
    当然具体采用什么方案必须经过实践的检验。就此先结贴,以后我会回馈实际方案执行的