Value LOBs in Oracle 26ai: The End of Chunked LOB Overhead
LOBs in Oracle
have historically been stored as chunks, with an associated LOB index segment
to allow navigation through the LOB structure. Because of this architecture,
when a query returns a LOB column, the client historically receives a pointer
to the LOB, and only when the client actually requests the LOB value does the
database send the data piece-by-piece across the network.
This design
still makes sense for very large LOBs, but today many modern JSON or text
payloads fall into an awkward middle area:
- too large for VARCHAR datatypes
- too small to justify chunking and LOB indexing
overhead
Let’s walk
through a simple demonstration.
demo@ADB26AI> create table
base_table
2 as
3 with
base_data as (
4
select rownum id
5
, 'Text' || rownum as data
6
from all_objects
7
where rownum <= 80 )
8 ,
one_clob as (
9
select json_arrayagg(json{*} returning clob) as jdoc
10
from base_data )
11
select rownum as pk
12
, one_clob.jdoc
13 from
one_clob , all_objects
14
where rownum <= 100;
Table created.
And we will
create a table with clob data type in a standard way and populate it with some
source data
demo@ADB26AI> create table
t_reference_clob( x number, y clob ) ;
Table created.
demo@ADB26AI>
demo@ADB26AI> insert into
t_reference_clob select * from base_table;
100 rows created.
demo@ADB26AI> commit;
Commit complete.
Now query the
table from a client session far from the database (in my case, Autonomous
Database in a remote region):
demo@ADB26AI> select *
from t_reference_clob;
100 rows selected.
Elapsed: 00:11:04.73
Statistics
----------------------------------------------------------
1070
recursive calls
17
db block gets
5713
consistent gets
5215
physical reads
2504
redo size
943880
bytes sent via SQL*Net to client
631599
bytes received via SQL*Net from client
2602 SQL*Net roundtrips to/from client
59
sorts (memory)
0
sorts (disk)
100
rows processed
This happens
because the client presumes the LOB might be arbitrarily large, so it retrieves
each row’s LOB in chunks, issuing repeated network requests.
From 23ai
onward, Oracle lets us tell the database that certain LOBs should be treated
like values rather than chunked LOB objects.
demo@ADB26AI> create table
t_value_clob( x number, y clob )
2
lob(y) query as value;
Table created.
demo@ADB26AI> insert into
t_value_clob select * from base_table;
100 rows created.
Now if I rerun the query,
notice the improvements in the round trips.
demo@ADB26AI> select *
from t_value_clob;
100 rows selected.
Elapsed: 00:00:03.12
Statistics
----------------------------------------------------------
23
recursive calls
16
db block gets
137
consistent gets
0
physical reads
2796
redo size
420380
bytes sent via SQL*Net to client
404
bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
1
sorts (memory)
0
sorts (disk)
100
rows processed
This is all
good If the Lobs are small, what if there is a mix ? we can also decide on query
by query basis on how would the lob data to be retrieved. Here is our original table query with
LOB_VALUE function.
demo@ADB26AI> select x,lob_value(y) from t_reference_clob;
100 rows selected.
Elapsed: 00:00:03.14
Statistics
----------------------------------------------------------
11
recursive calls
9
db block gets
16
consistent gets
112
physical reads
1552
redo size
420391
bytes sent via SQL*Net to client
404
bytes received via SQL*Net from client
2
SQL*Net roundtrips to/from client
1
sorts (memory)
0
sorts (disk)
100
rows processed
If the data is
JSON, then we can also provide the instruction to the database as part of the
JSON_SERIALIZE function.
demo@ADB26AI> select
x,json_serialize(y returning clob value) from
t_reference_clob;
100 rows selected.
Elapsed: 00:00:03.12
Statistics
----------------------------------------------------------
12
recursive calls
11
db block gets
16
consistent gets
100
physical reads
1700
redo size
420414
bytes sent via SQL*Net to client
404
bytes received via SQL*Net from client
2
SQL*Net roundtrips to/from client
1
sorts (memory)
0
sorts (disk)
100
rows processed
Why this
matters today.
- For most modern JSON use cases:
- ORDS APIs
- APEX pages
- Microservices
- Autonomous clients
- Cloud apps
…the payloads
are typically kilobytes, not gigabytes. The default LOB architecture is
overkill and causes unnecessarily high network latency.
With the new
approach, we can treat JSON CLOB as a value, not a chunked object, dramatically
reducing network round trips and improving performance—without changing the
data model.
If your
applications plan to leverage Oracle’s modern data types such as JSON or Vector,
Oracle Database 26ai will store these values as VALUE LOBs by default. This means
Oracle uses the VALUE LOB format internally for optimized retrieval and
processing.
demo-user@ADB26ai> create
table t ( x json ,y vector );
Table T created.
demo-user@ADB26ai> select
column_name, value_based
2 from
user_lobs
3* where table_name ='T' ;
COLUMN_NAME VALUE_BASED
______________ ______________
X YES
Y YES
No comments:
Post a Comment