项目中需要做一个船舶代理费的功能,针对代理的船进行收费,那么该功能的第一步便是选择进行代理费用信息的录入,在进行船舶选择的时候,发现加载相关船舶信息十分的慢,其主要在sql语句的执行,因为测试的时候数据较少,实际使用中,数据量较大。

关于regexp_substr函数的使用可查看Oracle通过一个字段的值将一条记录拆分为多条记录

需求和表结构

船舶相关的信息在系统中有船舶动态表(CBDT),另外有一张船舶代理费表(CBDLF),要求对于已经录入代理费的船舶不再出现在列表中(CBDLF表中有记录的需要过滤掉),CBDT中有一个合同清单字段,HTQD,该字段由分号";"拼接多个合同,由于选了船舶,需要计算这个船上所有合同的作业量(拿合同字段和其他表做连接),因此需要切割,方便后继的作业量计算,需求引入就是这里——需要切割合同清单字段(HTQD),存在几个合同,就要将该行变成几条记录。

  • 船舶动态表CBDT(肯定是省略的啦,哪有这么简单的表)
CBBH HC HTQD
0001 191210 N20191202-xx;N20191203-xx
  • 船舶动态表CBDLF
CBBH HC Free
0001 191210 12534.23

原来的方案

对于之前的sql,执行时间长达5秒多,最快也是4秒多,而且是只有一个月的数据。

看看原来的sql语句

select CBDT.CBBH, CBDT.HC,
regexp_substr(CBDT.HTBHQD,'[^;]+', 1,LEVEL,'i') HTTDBH
FROM CBDT
WHERE (CBDT.CBBH, CBDT.HC) not IN (SELECT CBBH, HC from CBDLFB)
AND KBRQ >= TO_DATE('2019-11-18', 'yyyy-mm-dd') and KBRQ <= TO_DATE('2019-12-18', 'yyyy-mm-dd')
connect by LEVEL <=regexp_count(CBDT.HTBHQD, ';') + 1

第一次尝试

使用了not in,显然这满足要求,但事实是not in的效率是十分低下的,(当初在用的时候,我也不知道啊,手动捂脸),所以应该改成join,有了下面的sql

select CBDT.CBBH, CBDT.HC,
regexp_substr(CBDT.HTBHQD,'[^;]+', 1,LEVEL,'i') HTTDBH
FROM CBDT
LEFT JOIN CBDLFB ON CBDT.CBBH = CBDLFB.CBBH and CBDT.HC = CBDLFB.HC
WHERE CBDLFB.CBBH is NULL
AND KBRQ >= TO_DATE('2019-11-18', 'yyyy-mm-dd') and KBRQ <= TO_DATE('2019-12-18', 'yyyy-mm-dd')
connect by LEVEL <=regexp_count(CBDT.HTBHQD, ';') + 1

这样改了之后,基本维持在4秒左右,当然,这还是不能忍的啊。

第二次尝试

通过改变时间,无论是延长还是缩短,sql执行的时间基本都在4秒左右,所以,目前的数据量对sql的影响不是很大了,那么肯定是sql本身的问题,去掉regexp_substr后,果然,只需要0.0xx秒的时间,所以基本确定了是这个函数的问题。开始度娘和谷歌。然而只找到了一个百度经验说性能问题,也没有说怎么解决。直到在谷歌上有人说,regexp_substr是正则,其本身效率就不高,不推荐。但是不推荐如前我的需求是必须要用啊(不知道有没有其他方案),找了许久依旧没有解决方案,回头再观察sql,regexp_substr是正则表达式毫无疑问,然后发现最后的regexp_count,这个那应该也是正则,但是regexp_count(CBDT.HTBHQD, ';')的意思是计算有几个分号,这个函数可以换掉啊。所以改用了LENGTH(CBDT.HTBHQD) -LENGTH(REPLACE(CBDT.HTBHQD,';','')) + 1 ,运行,奇迹发生了。

新的sql

select CBDT.CBBH, CBDT.HC,
regexp_substr(CBDT.HTBHQD,'[^;]+', 1,LEVEL,'i') HTTDBH
FROM CBDT
LEFT JOIN CBDLFB ON CBDT.CBBH = CBDLFB.CBBH and CBDT.HC = CBDLFB.HC
WHERE CBDLFB.CBBH is NULL
AND KBRQ >= TO_DATE('2019-11-18', 'yyyy-mm-dd') and KBRQ <= TO_DATE('2019-12-18', 'yyyy-mm-dd')
connect by LEVEL <= LENGTH(CBDT.HTBHQD) -LENGTH(REPLACE(CBDT.HTBHQD,';','')) + 1



速度提到了约:67%。

1秒多的时间,虽然较原来的5秒要好太多,但是1秒多的卡顿,始终还是不好,那么继续尝试吧。

找新的方案去了,待更新........(不到1秒内,誓不回);

——————————————我是分割线——————————————

我回来了,因为找到了终极优化,从5秒到0.025s,还是谷歌啊。

最后执行时间



话不多说,直接看改后的sql

select CBDT.CBBH, CBDT.HC,
regexp_substr(CBDT.HTBHQD,'[^;]+', 1,l) HTTDBH -- 原来的LEVEL换成了l,注意
FROM CBDT
LEFT JOIN CBDLFB ON CBDT.CBBH = CBDLFB.CBBH and CBDT.HC = CBDLFB.HC,
(SELECT LEVEL l FROM DUAL CONNECT BY LEVEL<=100) b -- 关键
WHERE CBDLFB.CBBH is NULL
AND KBRQ >= TO_DATE('2019-11-18', 'yyyy-mm-dd') and KBRQ <= TO_DATE('2019-12-18', 'yyyy-mm-dd')
AND l <= LENGTH(CBDT.HTBHQD) -LENGTH(REPLACE(CBDT.HTBHQD,';','')) + 1

之前的connect 是使用到sql最后,这样的方式会导致数据出现很多冗余,而且冗余特别严重,需要使用distinct,至于原因,还在找。使用regexp_substr函数必须配对使用connect,但是没想到居然可以这样使用。

5—>0.023 这速度提高99.5%;页面秒开,爽。

最后

本文可在我的小站中查看记Oracle中regexp_substr函数的一次调优

生命不息,使劲造。

记Oracle中regexp_substr的一次调优(速度提高95.5%)的更多相关文章

  1. Oracle中REGEXP_SUBSTR函数(转)

    Oracle中REGEXP_SUBSTR函数 Oracle中REGEXP_SUBSTR函数的使用说明: 题目如下:在oracle中,使用一条语句实现将'17,20,23'拆分成'17','20','2 ...

  2. Oracle中REGEXP_SUBSTR及其它支持正则表达式的内置函数小结

    Oracle中REGEXP_SUBSTR函数的使用说明: 题目如下:在oracle中,使用一条语句实现将'17,20,23'拆分成'17','20','23'的集合. REGEXP_SUBSTR函数格 ...

  3. Oracle中REGEXP_SUBSTR函数(字符串转多行)

    Oracle中REGEXP_SUBSTR函数 Oracle中REGEXP_SUBSTR函数的使用说明: 题目如下: 在oracle中,使用一条语句实现将'17,20,23'拆分成'17','20',' ...

  4. Oracle中REGEXP_SUBSTR函数

    Oracle中REGEXP_SUBSTR函数 Oracle中REGEXP_SUBSTR函数的使用说明: 题目如下: 在oracle中,使用一条语句实现将'17,20,23'拆分成'17','20',' ...

  5. x86服务器中网络性能分析与调优 转

    x86服务器中网络性能分析与调优 2017-04-05 巨枫 英特尔精英汇 [OpenStack 易经]是 EasyStack 官微在2017年新推出的技术品牌,将原创技术干货分享给您,本期我们讨论 ...

  6. 性能调优之提高 ASP.NET Web 应用性能的 24 种方法和技巧

    性能调优之提高 ASP.NET Web 应用性能的 24 种方法和技巧   poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对 ...

  7. 【Oracle】转:通过案例学调优之--Oracle Time Model(时间模型)

    转自:http://blog.51cto.com/tiany/1596012 通过案例学调优之--Oracle Time Model(时间模型) 数据库时间 优化不仅仅是缩短等待时间.优化旨在缩短最终 ...

  8. 记一次Web服务的性能调优

    前言 一个项目在经历开发.测试.上线后,当时的用户规模还比较小,所以刚刚上线的项目一般会表现稳定.但是随着时间的推移,用户数量的增加,qps的增加等因素会造成项目慢慢表现出网页半天无响应的状况.在之前 ...

  9. 利用ORACLE ADV 功能完成SQL TUNING 调优(顾问培训) “让DBA失业还是解脱?”

    oracle自动判断SQL性能功能. 11G的ADV,建议.SNAPSHOT,数据集合, 存储在oracle sys $_开头的表(10几条).  创建SNAPSHOT时选择天数, 默认14天. sq ...

随机推荐

  1. FreeRTOS优先级翻转

    举例 //高优先级任务的任务函数 void high_task(void *pvParameters) { while(1) { vTaskDelay(500); //延时500ms,也就是500个时 ...

  2. Spring中Bean的基本概念

    一.Bean的定义 <beans…/>元素是Spring配置文件的根元素,<beans…/>元素可以包含多个<bean…/>子元素,每个<bean…/> ...

  3. Oracle 多表插入

    多表插入 作用:一条INSERT语句可以完成向多张表的插入任务(Multitable insert).有两种形式:insert all与insert first,准备测试环境:1.创建表T并初始化测试 ...

  4. jenkins-harbor迁移(问题记录)

    读者们原谅,可能有点没头没尾,根据公司情况具体写的 需求:jenkins和harbor迁移另一台物理机 jenkins和harbor都迁移的情况,之前一直都是使用的是harbor的域名 我也在新的je ...

  5. SpringCloud_Eureka与Zookeeper对比

    关系型数据库与非关系型数据库及其特性: RDBMS(Relational Database Management System 关系型数据库) :mysql/oracle/sqlServer等   = ...

  6. http://www.easytest.xyz/login_action/

    http://www.easytest.xyz/login_action/一个挺牛逼的系统,有空学习下 https://www.cnblogs.com/1fengchen1/archive/2019/ ...

  7. 机械师实时调度示例(I) - 实时规划

    OptaPlanner创办人Geoffrey De Smet及其团队,在Red Hat 技术峰会上主题会场上,演示了一个通过OptaPlanner实现实时规划与调度的示例.Geoffrey及其团队专门 ...

  8. 小程序框架之视图层 View~获取界面节点信息

    获取界面上的节点信息 WXML节点信息 节点信息查询 API 可以用于获取节点属性.样式.在界面上的位置等信息. 最常见的用法是使用这个接口来查询某个节点的当前位置,以及界面的滚动位置. 示例代码: ...

  9. 《The One!团队》第八次作业:ALPHA冲刺(三)

    项目 内容 作业所属课程 所属课程 作业要求 作业要求 团队名称 < The One !> 作业学习目标 (1)掌握软件测试基础技术.(2)学习迭代式增量软件开发过程(Scrum) 第三天 ...

  10. 04 Spring的依赖注入

    依赖注入:Dependency Injection.它是 spring 框架核心 ioc 的具体实现. 我们的程序在编写时,通过控制反转,把对象的创建交给了 spring,但是代码中不可能出现没有依赖 ...