当前位置: 首页 > 知识库问答 >
问题:

SUBSTR在CLOB上的性能

柯波峻
2023-03-14

我有一个PL/SQL过程,它对varchar2参数执行大量substrs。我想删除长度限制,所以尝试将其更改为clob

工作正常,但性能受到影响,所以我做了一些测试(基于2005年的这些测试)。

更新:我可以用不同的Oracle版本和不同的硬件在几个不同的实例上重现这个过程,dbms_lob.substr总是明显比substr(CLOB)慢,而且比substr(VARCHAR2)慢得多。

Bob的结果和上面链接中的测试讲述了一个不同的故事。

有人能解释这一点吗,或者至少重现鲍勃或我的结果吗?谢了!

测试结果:

DECLARE
  l_text   VARCHAR2(30) := 'This is a test record';
  l_clob   CLOB := l_text;
  l_substr VARCHAR2(30);
  t TIMESTAMP;
BEGIN
  t := SYSTIMESTAMP;
  FOR i IN 1..100000 LOOP
    l_substr := SUBSTR(l_text,1,14);
  END LOOP;
  dbms_output.put_line( SYSTIMESTAMP - t || ' (VARCHAR2)');

  t := SYSTIMESTAMP;
  FOR i IN 1..100000 LOOP
    l_substr := SUBSTR(l_clob,1,14);
  END LOOP;
  dbms_output.put_line( SYSTIMESTAMP - t || ' (CLOB SUBSTR)');

  t := SYSTIMESTAMP;
  FOR i IN 1..100000 LOOP
    l_substr := DBMS_LOB.SUBSTR(l_clob,14,1);
  END LOOP;
  dbms_output.put_line( SYSTIMESTAMP - t || ' (DBMS_LOB.SUBSTR)');
END;

共有1个答案

安聪
2023-03-14

(谎言,该死的谎言,还有基准……)

我重新运行了您的测试10次,将字符串扩展为整整30个字符,得到了以下平均结果:

+000000000 00:00:00.011694200 (VARCHAR2)
+000000000 00:00:00.901000600 (CLOB SUBSTR)
+000000000 00:00:00.013169200 (DBMS_LOB.SUBSTR)

然后,我将子字符串范围更改为5,14(对于dbms_lob.substr,为14,5)并得到:

+000000000 00:00:00.011731000 (VARCHAR2)
+000000000 00:00:01.010840000 (CLOB SUBSTR)
+000000000 00:00:00.011427000 (DBMS_LOB.SUBSTR)
+000000000 00:00:00.013578900 (VARCHAR2)
+000000000 00:00:00.964527400 (CLOB SUBSTR)
+000000000 00:00:00.011416800 (DBMS_LOB.SUBSTR)
+000000000 00:00:00.011210200 (VARCHAR2)
+000000000 00:00:00.916439800 (CLOB SUBSTR)
+000000000 00:00:00.013781300 (DBMS_LOB.SUBSTR)

我的结论是,在处理CLOB时,最好使用dbms_lob.SUBSTR,因为与使用SUBSTR处理“普通”VARCHAR2相比,它似乎没有任何性能损失。针对CLOB的SUBSTR似乎遭受了重大的性能损失。对于记录-OS=HP/UX(Unix变体),Oracle Version=11.1,Processor=HP Itanium 2-plex。YMMV.

分享和享受。

因为如果值得做就值得过度做,这里有一些字符串扩展到32767个字符的结果。每组结果给出的子字符串范围:

1, 25000
+000000000 00:00:00.198466400 (VARCHAR2)
+000000000 00:00:02.870958700 (CLOB SUBSTR)
+000000000 00:00:00.174490100 (DBMS_LOB.SUBSTR)

1000, 25000
+000000000 00:00:00.253447900 (VARCHAR2)
+000000000 00:00:02.491790500 (CLOB SUBSTR)
+000000000 00:00:00.193560100 (DBMS_LOB.SUBSTR)

10000, 25000
+000000000 00:00:00.217812000 (VARCHAR2)
+000000000 00:00:02.268794800 (CLOB SUBSTR)
+000000000 00:00:00.222200200 (DBMS_LOB.SUBSTR)

(亲爱的朋友们,再一次向缺口走去,再一次……)

重新运行基准测试,将CLOB的大小更改为3276700,并从中间开始从2475000取子字符串,长度为25000,我得到:

+000000000 00:00:00.176883200 (VARCHAR2)
+000000000 00:00:02.069482600 (CLOB SUBSTR)
+000000000 00:00:00.175341500 (DBMS_LOB.SUBSTR)

(注意更改只影响最后两个测试)。

 类似资料:
  • 我有一个XML存储在CLOB中。为了显示来自XML的特定数据,我需要运行各种substr和instr函数。 我当前的代码使用varchar2(32000)变量处理它,如下所示: 我编写了一个匿名块来测试子字符串的限制,如下所示: 我注释掉了第二个子字符串,只是为了看看如果我将str_length更改为32000以下,表是否会填充数据,并且它确实被填充了。 这是我的输出 下面是我的输出:

  • 问题内容: 由此产生的数据集只应delimters之前显示的字符串,并以正确的顺序。程序包中已经存在的“当前查询”是这样的(DDL和DML在帖子的底部): 哪些结果会生成以下数据集: PS。 我只需要专栏,但我也包括其他专栏,但确实添加了上下文。 我发现查询有点混乱并且难以阅读,因此我尝试使用@vkp并提出了建议,我想出了以下查询,结果与上面的数据集相同。 然而,从@ MathGuy的答案,似乎和

  • substr 方法 从起始索引位置提取字符串中指定数目的字符。 语法: stringObject.substr( start_index, length ); 参数说明: start_index - 必需。要抽取的子串的起始下标。必须是数值。如果是负数,那么该参数声明从字符串的尾部开始算起的位置。也就是说,-1 指字符串中最后一个字符,-2 指倒数第二个字符,以此类推。 substrment

  • 描述 (Description) 此方法用于返回字符串的必需子字符串。 它接受一个整数值,表示子字符串的起始值和字符串的长度,并返回所需的子字符串。 如果起始值为负,则substr()方法将其用作字符串末尾的字符索引。 语法 (Syntax) 下面给出了JavaScript的substr()方法的语法。 我们可以在CoffeeScript代码中使用相同的方法。 string.substr(star

  • 描述 (Description) 此函数返回EXPR的子字符串,从字符串中的OFFSET开始。 如果OFFSET为负数,则从字符串末尾开始那么多字符。 如果指定了LEN,则返回该字节数,或者返回所有字节,直到未指定为字符串结尾。 如果LEN为负数,则将多个字符留在字符串末尾。 如果指定了REPLACEMENT,则使用REPLACEMENT字符串替换子字符串。 如果指定超出字符串末尾的子字符串,则仅

  • 此方法从特定字符串获取子字符串。 语法 (Syntax) substr(string1,index,count) 参数 (Parameters) string1 - 源字符串。 index - 子字符串的起始索引位置。 count - 子字符串的字符数。 返回值 (Return Value) 返回子字符串。 例子 (Example) /* Main program */ a = "Hello