Skip to Main Content
  • Questions
  • Comparing dbms_lob.writeappend with the string concatenation operator ||

Breadcrumb

Question and Answer

Connor McDonald

Thanks for the question, Dieter.

Asked: December 12, 2022 - 8:56 am UTC

Last updated: December 19, 2022 - 5:01 am UTC

Version: 19.3

Viewed 1000+ times

You Asked

I have been using the dbms_lob.append and dbms_lob.writeappend api for many years when having to append a VARCHAR2 or CLOB value to a CLOB value but recently noticed that it (now) also possible to just use string concatenation operator || to do this.
This is clearly a lot more convenient but I'm wondering of there are any restrictions, performance hits or any other disadvantages in using || with CLOB values? Is Oracle generally moving towards being able to use CLOB and VARCHAR2 interchangeably?

using dbms_lob:
   c CLOB;
   t VARCHAR2(32767) := 'abc';
BEGIN
   dbms_lob.createtemporary(lob_loc=>c, cache=>TRUE);
   dbms_lob.writeappend(lob_loc=>c, amount=>LENGTH(t), buffer=>t);
   dbms_lob.freetemporary(lob_loc=>c);
END;


using ||:
   c CLOB;
   t VARCHAR2(32767) := 'abc';
BEGIN
   dbms_lob.createtemporary(lob_loc=>c, cache=>TRUE);
   c := c || t;
   dbms_lob.freetemporary(lob_loc=>c);
END;


and Connor said...

Convenience has a price ... sometimes :-)

I wrote this up recently

https://connor-mcdonald.com/2022/12/06/faster-operations-with-clobs/

For most operations, you'd hardly notice it, but there are some circumstances where it has a cost

Rating

  (2 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

non-authoritative opinion

A reader, December 13, 2022 - 8:28 am UTC

First. Use of
amount=>LENGTH(t)
is unsafe in the multibyte database. The character of varchar2 and clob may have different lengths in characters.
Second. LOB can be persistent (select for update/DML returning), temporary (createtemporary) or abstract (just assignment).
Before 21c abstract lob is faster for small sizes (256k?). With an abstract/temporary lob, writeappend(length2()) is faster.
For a persistent LOB, concatenation || is faster.

Dieter, December 13, 2022 - 2:25 pm UTC

Thank you for the feedback.

I did some quite extensive testing on a variety of development and production system before migrating code to use the string concatenation operator for CLOB values with a test script that can be boiled down to the following code.

In general the results did not show significant differences and typically the differences are around +/- 5%.

CREATE TABLE temp_clob_perf
(
 id NUMBER GENERATED BY DEFAULT ON NULL AS IDENTITY PRIMARY KEY,
 tx VARCHAR2(1000),
 el NUMBER
);

TRUNCATE TABLE temp_clob_perf;

DECLARE
 t VARCHAR2(32767);
 c CLOB;
 s NUMBER;
 e NUMBER;
 l NUMBER;
 a dbms_utility.number_array;
BEGIN
 a(1) := 1;
 a(2) := 10;
 a(3) := 100;
 a(4) := 1000;
 a(5) := 10000;

 -- process the different chunk sizes to add
 FOR idx IN 1 .. a.COUNT LOOP
  l := 100000 / a(idx);
  t := RPAD('*', a(idx), '*');

  -- dbms_lob.writeappend
  dbms_lob.createtemporary(lob_loc=>c, cache=>TRUE);
  s := dbms_utility.get_time();
  -- test 10 times and use average
  FOR i IN 1 .. 10 LOOP
   -- iterate l times to reach final size
   FOR i IN 1 .. l LOOP
    dbms_lob.writeappend(lob_loc=>c, amount=>LENGTH(t), buffer=>t);
   END LOOP;
  END LOOP;
  e := dbms_utility.get_time();
  INSERT INTO temp_clob_perf (tx, el) VALUES ('dbms_lob.writeappend: '||l||' concatenations with each '||LENGTH(t)||' chars', (e - s) / 10);
  dbms_lob.freetemporary(lob_loc=>c);

  -- string concatenation
  dbms_lob.createtemporary(lob_loc=>c, cache=>TRUE);
  s := dbms_utility.get_time();
  -- test 10 times and use average
  FOR i IN 1 .. 10 LOOP
   -- iterate l times to reach final size
   FOR i IN 1 .. l LOOP
    c := c || t;
   END LOOP;
  END LOOP;
  e := dbms_utility.get_time();
  INSERT INTO temp_clob_perf (tx, el) VALUES ('string concatenation: '||l||' concatenations with each '||LENGTH(t)||' chars', (e - s) / 10);
  dbms_lob.freetemporary(lob_loc=>c);
 END LOOP;
END;
/

SELECT * FROM temp_clob_perf ORDER BY ID;


Connor McDonald
December 19, 2022 - 5:01 am UTC

So many permutations are possible, but here's some results from my own database (AL32UTF8)

https://connor-mcdonald.com/2022/12/06/faster-operations-with-clobs/

TL;DR - I found || to be the most suspectible to slow downs

More to Explore

Administration

Need more information on Administration? Check out the Administrators guide for the Oracle Database