栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

REGEXP_SUBSTR与INSTR和SUBSTR的性能和可读性

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

REGEXP_SUBSTR与INSTR和SUBSTR的性能和可读性

我已经张贴出如何解决使用这一问题的答案

INSTR
,并
SUBSTR
以正确的方式。

在本“答案”中,我解决了另一个问题-哪种解决方案更有效。我将在下面解释测试,但这是最重要的一点:

REGEXP
解决方案花费的 时间
INSTR/SUBSTR
解决方案 长40倍

设置
:我创建了一个包含150万个随机字符串的表(所有字符串长度均为8个字符,全部为大写字母)。然后,我修改了10%的字符串以添加子字符串

'PLE'
,再修改了10%的添加了a
'#'
,再修改了10%的添加
'ALL'
。我这样做的分裂在位置上的原始字符串
mod(rownum, 9)
-这是0和8之间的数字-
和连接
'PLE'
'#'
'ALL'
在该位置。当然,这不是获取我们所需测试数据的最有效或最优雅的方法,但这无关紧要-
关键是创建测试数据并将其用于我们的测试中。

所以:现在我们有了一个只有一列的表,其中

data1
有150万行中的一些随机字符串。各10%的子串
PLE
#
ALL
在其中。

测试包括创建

data2
与原始帖子中相同的新字符串。我没有将结果插入表中;而是将结果插入表中。无论如何
data2
计算, 其重新
插入 表中的时间都应该相同。

相反,我将主查询放在一个外部查询中,该查询用于计算结果

data2
值的长度之和。这样,我保证优化器不能采用快捷方式:
data2
必须生成所有值,必须测量它们的长度,然后将它们求和。

下面是创建基表所需的语句,我将其称为

table_z
,然后运行了查询。

create table table_z asselect dbms_random.string('U', 8) as data1 from dualconnect by level <= 1500000;update table_z set data1 = casewhen rownum between      1 and 150000 then substr(data1, 1, mod(rownum, 9))          || 'PLE' || substr(data1, mod(rownum, 9) + 1)when rownum between 150001 and 300000 then substr(data1, 1, mod(rownum, 9))          || '#'   || substr(data1, mod(rownum, 9) + 1)when rownum between 300001 and 450000 then substr(data1, 1, mod(rownum, 9))          || 'ALL' || substr(data1, mod(rownum, 9) + 1)          endwhere rownum <= 450000;commit;

INSTR/SUBSTR
解决方案

select sum(length(data2))from (select data1,        case          when instr(data1, 'PLE', 2) > 0 then substr(data1, 1, instr(data1, 'PLE', 2) - 1)         when instr(data1, '#'  , 2) > 0 then substr(data1, 1, instr(data1, '#'  , 2) - 1)         when instr(data1, 'ALL', 2) > 0 then substr(data1, 1, instr(data1, 'ALL', 2) - 1)         else data1 end       as data2from   table_z);SUM(LENGTH(DATA2))------------------          107133521 row selected.Elapsed: 00:00:00.73

REGEXP
解决方案

select sum(length(data2))from (select data1,        COALESCE(REGEXP_SUBSTr(DATA1, '(.+?)PLE',1,1,null,1)      ,REGEXP_SUBSTr(DATA1, '(.+?)#',1,1,null,1)      ,REGEXP_SUBSTr(DATA1, '(.+?)ALL',1,1,null,1)      ,DATA1)       as data2from   table_z);SUM(LENGTH(DATA2))------------------          107133521 row selected.Elapsed: 00:00:30.75

在任何人提出这些建议之前,我都重复了两次查询;第一个解决方案的运行时间通常为0.75到0.80秒,第二个查询的运行时间为30到35秒。慢40倍以上。(因此,编译器/优化器花费时间来编译查询不是问题;这实际上是执行时间。)而且,这与从基表中读取150万个值无关,这与两种测试的时间都比处理要少得多。无论如何,我都会先运行

INSTR/SUBSTR
查询,因此,如果有任何缓存,那么该
REGEXP
查询将是一个受益的地方。

编辑
:我只是想出了建议的REGEXP解决方案中的一个低效率。如果我们将搜索模式锚定到字符串的开头(例如

'^(.+?)PLE'
,注意
^
锚点),则REGEXP查询的运行时间将从30秒降至10秒。显然,Oracle实现不足以识别这种等效性,并尝试从第二个字符,第三个字符等进行搜索。执行时间仍然要长15倍;15
<40,但仍然相差很大。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/574987.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号