Oracle insert into太慢

insert into太慢

insert into太慢?Roger 带你找真凶
运营商客户的计费库反应其入库程序很慢,应用方通过监控程序发现主要慢在对于几个表的insert操作上。按照我们的通常理解,insert应该是极快的,为什么会很慢呢?而且反应之前挺好的。这有点让我百思不得其解。通过检查event也并没有发现什么奇怪的地方,于是我通过10046 跟踪了应用的入库程序,如下应用方反应比较慢的表的insert操作,确实非常慢,如下所示:
这里写图片描述
*我们可以发现,insert了4579条数据,一共花了27.41秒;其中有24.02秒是处于等待的状态。而且等待事件为顺序读.很明显这通常是索引的读取操作,实际上检查10046 trace 裸文件,发现等待的对象确实是该表上的2个index。
同时我们从上面10046 trace可以看出,该SQL执行之所以很慢,主要是因为存在了大量的物理读,其中4579条数据的insert,物理读为4534;这说明什么问题呢? 这说明,每插入一条数据大概产生一个物理读,而且都是index block的读取。很明显,通过将该index cache到keep 池可以解决该问题。 实际上也确实如此,通过cache后,应用反馈程序快了很多。
那么对该问题,这里其实有几个疑问,为什么这里的SQL insert时物理读如此之高? oracle的keep pool对于缓存对象的清理机制是如何的?
下面我们通过一个简单的实验来进行说明。
首先我们创建2个测试表,并创建好相应的index,如下所示:
这里写图片描述
创建表和索引并插入数据
这里写图片描述
从前面的信息我们可以看出,object_name上的index其实聚簇因子比较高,说明其数据分布比较离散。

接着我们现在将index都cache 到keep 池中,如下:
这里写图片描述
这里需要注意的是,仅仅执行alter 命令是不够的,我们还需要手工将index block读取到keep池中,如下:
这里写图片描述
第一次读取并检查
这里写图片描述
第二次读取并检查
这里写图片描述
第三次读取并检查
这里写图片描述
我们可以大致看出,db keep pool 也是存在LRU的,而且对于block的清除机制是先进先出原则。那么为什么前面的问题中,insert会突然变慢呢?

下面我们来进行3次insert 测试。

第一次
这里写图片描述
使用10046事件跟踪
这里写图片描述
第二次
这里写图片描述
第三次
这里写图片描述
使用10046事件跟踪
这里写图片描述
从测试来看,随着表的数据越来越大,insert的效率会越来越低,也其实主要在于index的问题。我们可以发现,3次测试过程中,物理读越来越大,而且db file sequential read的等待时间分别从0.5秒,增加到0.56秒,最后增加到1.07秒。 为什么会出现这样的情况呢?

随着表数据的日益增加,导致表上的index也不断增大,同时index的离散度比较高,这样就导致每次insert时,oracle在进行index block读取时,可能在buffer cache中都无法命中相应的block;这样就会导致每次读取需要的index block时,可能都要进行物理读,这势必会导致性能问题的出现。同时默认的default buffer cache pool虽然也可以缓存index 块,但是也要同时缓存其他的数据块,这样很容易导致相关的index block被从buffer cache pool中移走。所以这也是前面为什么需要将index cache到keep 池的原因。

  • 9
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: Oracle中的insert into select语句可能是由于以下原因: 1. 数据量过大:如果插入的数据量非常大,那么插入操作可能会变得非常缓。这可能是由于磁盘I/O速度或者网络带宽不足等原因导致的。 2. 索引问题:如果目标表中有大量索引,那么插入操作可能会变得非常缓。这是因为每次插入都需要更新索引,这会导致额外的I/O操作和CPU开销。 3. 锁问题:如果目标表正在被其他会话锁定,那么插入操作可能会被阻塞,从而变得非常缓。 4. SQL语句优化问题:如果insert into select语句中的select语句没有被优化,那么插入操作可能会变得非常缓。可以通过使用适当的索引、分区表等技术来优化select语句。 为了解决这些问题,可以采取以下措施: 1. 分批插入:将大的插入操作分成多个小的插入操作,每次插入一部分数据。这可以减少每次插入的数据量,从而提高插入速度。 2. 禁用索引:在插入操作之前禁用目标表中的索引,插入完成后再重新启用索引。这可以减少每次插入时的I/O操作和CPU开销。 3. 优化SQL语句:使用适当的索引、分区表等技术来优化select语句,从而提高插入操作的速度。 4. 检查锁问题:检查目标表是否被其他会话锁定,如果是,则等待锁释放后再进行插入操作。 ### 回答2: Oracle的数据插入操作是整个数据库操作中最为基础,同时也是最为频繁的操作之一,因此在性能方面也要求较高。 但是有时候在使用insert into select语句进行向目标表插入数据的时候却会出现插入速度的情况,下面给出一些可能导致该问题的原因: 1. 数据库中的表结构设计不合理,比如表中缺少必要的索引或者字段类型不匹配、字段长度不合适等,都可能影响插入性能。 2. 数据源表的查询有性能问题,比如查询语句中包含大量计算、多表联查等符合复杂查询的情况,也可能导致插入缓。 3. 目标表的约束条件,比如唯一性约束等,会导致插入数据时需要进行大量的重复检查,从而影响插入性能。 4. 数据库的相关参数设置不合理,如日志模式选择不当、缓存命中率低等,都可能对插入操作产生负面影响。 解决这个问题的方法有很多,具体要根据实际情况而定。比如对表结构进行优化、对查询语句进行优化、调整数据库的相关参数等,都是可以提高插入效率的有效方法。 总之,在使用insert into select语句进行数据插入的时候,我们需要注意各种因素对性能的影响,及时进行优化调整,才能保证插入操作的高效性。 ### 回答3: Oracle在执行INSERT INTO SELECT语句时可能会出现的情况,这些情况可能会导致系统的性能下降。以下是导致INSERT INTO SELECT语句的常见原因: 1. 大量数据插入或更新 如果表中有大量的数据需要插入或更新,那么执行INSERT INTO SELECT语句时,数据库需要花费大量的时间和资源来插入这些数据。在这种情况下,可以考虑分批插入或更新,或者调整Oracle数据库的缓存大小和缓存优化参数来提高执行效率。 2. 缺乏合适的索引 如果表中缺乏合适的索引,那么在执行INSERT INTO SELECT语句时,数据库需要进行全表扫描,这将花费大量的时间和资源。在这种情况下,可以考虑创建合适的索引来提高执行效率。 3. 锁定问题 当多个用户同时使用同一张表进行数据插入或更新时,可能会出现锁定问题,从而导致INSERT INTO SELECT语句速执行。在这种情况下,可以考虑修改锁定策略或者优化数据库连接池来解决问题。 4. 数据库空间不足 如果数据库所在的磁盘空间不足,那么在执行INSERT INTO SELECT语句时,数据库可能会出现速执行的情况。在这种情况下,可以考虑扩大数据库磁盘空间或者删除旧数据来释放硬盘空间。 总之,如果Oracle执行INSERT INTO SELECT语句的话,我们可以通过分批插入、创建索引、修改锁定策略、优化连接池、扩大小空间等方案来解决问题。这需要根据具体情况进行分析和调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值