当前位置: 首页 > news >正文

案例-索引对于并发Insert性能优化测试

前言

  最近因业务并发量上升,开发反馈对订单表Insert性能降低。应开发要求对涉及Insert的表进行分析并提供优化方案。
  一般对Insert 影响基本都在索引,涉及表已按创建日期做了分区表,索引全部为普通索引未做分区索引。

优化建议:

  • 1、将UNIQUE改为HASH(64) GLOBAL INDEX,NORMAL改为Local INDEX。

  优化思路:分散IO及减少维护成本,Oracle在索引分裂是当索引块空间不足时,通过分裂为新块以容纳新数据的操作,会引发性能问题。普通索引和分区索引(尤其是本地分区索引)在索引分裂时的行为存在显著差异。

  • 2、RAC环境使用TAF(Transparent Application Failover)即透明应用程序故障转移技术,通过应用细化连接,减少RAC集群的内网交互,从而减少RAC集群的负载。

优化方案压力测试

表1:

  • 数据量:1.5亿,需要调整的索引:唯一索引:3,普通索引:3

    image.png

  • 优化后:

    image.png

表2:

  • 数据量:1.4亿,需要调整的索引:唯一索引:1,普通索引:4

    image.png

  • 优化后:

    image.png

RAC的TAF技术测试

  • 连接SCAN_IP 测试双节点插入
  • 连接单节点VIP 测试单节点插入

并发测试脚本:《Oracle&Python并发Insert测试脚本.pdf》

压力测试结果:

  • 并发:100,插入数据:80w

    image.png

  • 小结分析:

1、表1的优化效果提升20%以上表2的优化效果差强人意(-1%至-4%之间)
原因分析:Insert 语句导致:直接复制表中的单条记录,然后对唯一索引字段修改为UUID值,日期字段为:sysdate,其它字段为固定值。
表1:索引字段都有插入数据且值为UUID或其它索引字段均有日期字段
表2:索引字段有3个索引值为Null(索引无操作),另一个索引插入的值为固定值(无法做到IO分散),仅唯一索引的值为UUID(有效果)。

2、单节点比双节点插入效率-50%左右,原因为双节点分摊了并发压力,相关于单节点的:并发50,40w的数据插入,因此双节点要比单节点同样的压力要更优。

3、最终确认方案仅对表1进行索引优化,其它保持不变。

4、声明:此方案提升效果仅适用于此压测数据,而生产环境很难达到并发:100 数据量:80w 耗时:100s插入完成,并且为单条Insert语句。当并发压力未传到数据库的情况下,优化效果可能并不明显。因此生产的性能问题还需要与开发一起综合设计优化方案为最佳。

验证测试:

  • 表说明:优化前:A_OLD、优化后:A_NEW,数据量:1.5亿
  • 测试方向:对唯一索引、普通索引优化为:全局HASH分区索引(64)、本地索引提升效果。

查询索引

SELECT 
    i.TABLE_NAME,
    i.index_type,
    p.locality ,
    i.UNIQUENESS,
    LISTAGG(ic.COLUMN_NAME, ',') WITHIN GROUP (ORDER BY ic.COLUMN_POSITION) AS INDEX_COLUMNS,
    i.INDEX_NAME
FROM 
    ALL_INDEXES i
JOIN 
    ALL_IND_COLUMNS ic ON i.INDEX_NAME = ic.INDEX_NAME
left join user_part_indexes p on i.INDEX_NAME = p.INDEX_NAME
WHERE 
    i.TABLE_NAME in ('A_NEW','A_OLD')
GROUP BY 
    i.TABLE_NAME,i.INDEX_NAME,i.UNIQUENESS,p.locality ,i.index_type, i.UNIQUENESS
order by 3,1;

TABLE_NAME  INDEX_TYPE  LOCALI  UNIQUENES    INDEX_COLUMNS   INDEX_NAME
----------- ----------- ------  ---------    --------------- ------------------
A_NEW       NORMAL      GLOBAL  UNIQUE       ID              IDX_UN_ID_A_NEW
A_OLD       NORMAL              UNIQUE       ID              IDX_UN_ID_A_OLD
A_NEW       NORMAL      LOCAL   NONUNIQUE    BANK_NO         IDX_BANK_NO_A_NEW
A_OLD       NORMAL              NONUNIQUE    BANK_NO         IDX_BANK_NO_A_OLD


并发测试脚本:<Oracle与Python并发Insert测试>

脚本输出

略......
2025-04-09 18:52:22,494 - INFO - INS:twodb1|SID:1006: A_OLD:8000: 530行/秒
2025-04-09 18:52:22,517 - INFO - INS:twodb1|SID:1923: A_OLD:8000: 523行/秒
2025-04-09 18:52:22,707 - INFO - INS:twodb1|SID:1858: A_OLD:8000: 529行/秒
2025-04-09 18:52:22,781 - INFO - INS:twodb1|SID:1925: A_OLD:8000: 527行/秒
2025-04-09 18:52:22,798 - INFO - 表    名:A_OLD
2025-04-09 18:52:22,798 - INFO - 开始时间: 2025-04-09 18:52:07
2025-04-09 18:52:22,798 - INFO - 结束时间: 2025-04-09 18:52:22
2025-04-09 18:52:22,799 - INFO - 耗    时: 15.61  seconds
2025-04-09 18:52:22,799 - INFO - 并    行: 100
2025-04-09 18:52:22,799 - INFO - 数 据 量: 800000
2025-04-09 18:52:22,799 - INFO - 速    度: 51260 行/秒
2025-04-09 18:52:22,799 - INFO - -----------------------wait 10 min------------------------------------

略......
2025-04-09 19:02:40,629 - INFO - INS:twodb1|SID:1709: A_NEW:8000: 557行/秒
2025-04-09 19:02:40,655 - INFO - INS:twodb1|SID:150: A_NEW:8000: 556行/秒
2025-04-09 19:02:40,658 - INFO - INS:twodb1|SID:1217: A_NEW:8000: 555行/秒
2025-04-09 19:02:40,660 - INFO - INS:twodb1|SID:716: A_NEW:8000: 553行/秒
2025-04-09 19:02:40,677 - INFO - 表    名:A_NEW
2025-04-09 19:02:40,678 - INFO - 开始时间: 2025-04-09 19:02:26
2025-04-09 19:02:40,678 - INFO - 结束时间: 2025-04-09 19:02:40
2025-04-09 19:02:40,678 - INFO - 耗    时: 14.63  seconds
2025-04-09 19:02:40,678 - INFO - 并    行: 100
2025-04-09 19:02:40,678 - INFO - 数 据 量: 800000
2025-04-09 19:02:40,678 - INFO - 速    度: 54695 行/秒
2025-04-09 19:02:40,681 - INFO - --------------程序执行结束-----------------------------------

测试结果:

image.png

测试小结

  • 从上面的测试结果来看,普通索引(UNIQU、NORMAL)优化为(HASH(64)INDEX、Local INDEX)效果提升6%以上。

分析:普通索引、本地分区索引‌、全局分区索引‌

  • ‌1、 普通索引
    ‌结构影响‌:普通索引基于整个表构建,索引分裂会影响整个索引树结构。例如,频繁插入可能导致叶子块分裂(如50-50分裂或99-分裂),甚至触发分支节点分裂,增加I/O和锁争用。
    ‌维护开销‌:每次分裂需更新整个索引结构,高并发写入时可能成为性能瓶颈。
    ‌热点问题‌:所有插入操作集中在同一索引结构,可能导致块竞争(如索引块争用)。
  • 2、 本地分区索引(Local Partitioned Index)‌
    ‌分区独立性‌:每个分区的索引独立维护,索引分裂仅发生在操作对应的分区内,不影响其他分区。
    ‌维护效率‌:分区操作(如TRUNCATE或DROP)仅影响本地索引的对应分区,维护更快且无需重建整个索引。
    ‌并发优化‌:不同分区的插入操作分散到各自的索引分区,减少锁争用和热点问题。
    ‌适用场景‌:适合数据有明显分区键(如时间范围),且频繁写入的场景。
  • ‌3、 全局分区索引(Global Partitioned Index)‌
    ‌跨分区结构‌:索引的分区方式与表分区无关,索引分裂可能影响整个全局索引的结构,类似普通索引,优化是分散IO。
    ‌维护开销‌:对表分区的维护操作(如删除分区)可能导致全局索引失效,需重建或命令加:update indexes来维护索引。
    ‌灵活性‌:分区键可独立于表,但牺牲了本地索引的维护优势。
  • ‌4. 索引分裂优化策略‌
    ‌普通索引‌:使用REVERSE KEY索引或调整PCTFREE减少分裂频率。
    ‌本地分区索引‌:合理设计分区键,确保写入均匀分布到不同分区。
    ‌全局索引‌:慎用,仅在查询模式需要时使用,并定期维护。
  • 5、索引相关案例:数据裁剪偶遇【enq: TX - index contention】

总结‌

  • 本地分区索引‌在分裂和维护效率上显著优于普通索引和全局索引,尤其适合分区表的高并发场景。
  • 普通索引‌简单但易成瓶颈;‌全局索引‌灵活性高但维护成本大。设计时应根据数据分布和查询需求权衡选择。
  • 全局分区索引也有某些局限,那就是如果查询条件跨多个索引分区,则效率就下降了,因此全局分区索引对范围查询(Between…and…、>、<、<>等)操作通常性能不好。总之,全局分区索引将索引高度降低了,能提升性能,但如果横向扩展访问多个分区索引树,性能又会下降。
  • 周期性的开启Oracle 的“索引监控功能”,对不需要的索引及时清理。

相关文章:

  • 初阶数据结构--二叉树OJ训练
  • 渗透测试学习-概述
  • 搭载DeepSeek|暴雨AI教育一体机加速AI教育普及
  • # linux 设置宽容模式
  • onlyoffice 在线编辑集成
  • 【数据结构_8】栈和队列
  • Java基础——面试自我总结
  • Linux基础IO(七)之理解文件系统
  • 文心一言开发指南03——千帆大模型平台产品优势
  • 力扣每日打卡 3396. 使数组元素互不相同所需的最少操作次数(简单)
  • 【NLP】 22. NLP 现代教程:Transformer的训练与应用全景解读
  • 高速电路中的电阻、电容的选型及应用
  • SCP-Firmware安全通告:CVE-2024-11863和CVE-2024-11864
  • 数组中的第K个最大元素
  • 运行便携软件提示系统从服务器返回一个参照问题解决
  • CVE重要漏洞复现-Fastjson1.2.24-RCE漏洞
  • 一键部署ai画图环境foooocus colab
  • c++------模板进阶
  • 计算机组成原理 第 1 章 概 论
  • C++基础系列【36】异常处理
  • 美股再遭重挫,标普500指数11个板块全线溃败
  • 中印尼“2+2”:中国周边外交的范式突破与东南亚棋局重构
  • “中国共产党的故事——习近平新时代中国特色社会主义思想在重庆的实践”重庆经贸推介会成功举办
  • 大气科学家、北京大学副教授李成才逝世,终年56岁
  • 罗马教皇方济各去世,享年88岁
  • 寻女19年的“棉花糖爸爸”明将办团圆宴,大女儿:妹妹是片区销售主管