Performance between enable/eisable storage in row LOBs?
We could add enable or disable storage in row attribute for Oracle CLOB/BLOB columns, by default it's enabled. If the LOB value is less than 4000 bytes, the LOB value will be stored inline the row piece, else both of these type will store the value in LOB segment. Is there any difference between them when LOB value is stored out of row? Let's start a demo, I create this demo on a 10g database, create a demo table contains two CLOB columns, and populate them with the same value, the table just contains one row, as following :
SQL> create table t_lobtest (col1 clob, col2 clob)
2 lob (col2) store as (disable storage in row);
Table created.
ASQL> SELECT DBMS_LOB.GETLENGTH(COL1) COL1_LEN,
2 DBMS_LOB.GETLENGTH(COL2) COL2_LEN
3 FROM T_LOBTEST;
COL1_LEN COL2_LEN
-------- --------
7989 7989
1 rows returned.
The LOB value length is greater than 4000, so the value are stored out of row for both columns, then let's select them in SQL*Plus and do a statistics trace, you will see that consistent gets for the two LOB columns are different.
SQL> select col1 from t_lobtest;
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
11 consistent gets
4 physical reads
0 redo size
1213 bytes sent via SQL*Net to client
829 bytes received via SQL*Net from client
5 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
SQL> select col2 from t_lobtest;
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
19 consistent gets
4 physical reads
0 redo size
1141 bytes sent via SQL*Net to client
781 bytes received via SQL*Net from client
5 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
However the physical reads are both 4 due to direct path read of LOB, but for consistent gets, the disabled column has more gets than the enabled column. According to my research of LOB value, for LOB columns with enable storage in row attribute, if the chunks are less than 12, then the chunk address will be stored in row piece ( LOB_ID, CHUNK1, CHUNK2, ..., CHUNK12 ), and the LOB index will not store the chunk address which already stored in the row piece. for LOBs with disable storage in row attribute, only LOB_ID is stored in the row piece, every chunk addresses are stored in the LOB index. For this case, when accessing column "COL1", no LOB index access is required, but for column "COL2", oracle have to touch LOB index's block, that's where the extra consistent gets come from.
For high execution frequency SQLs, take this into account when tuning. You can define the proper chunk size to reduce the entries in LOB index for performance improvement.
