Доброго времени суток всем!
Недавно обнаружил в отчете statspack большое количество физических чтений у LOB-сегмента.
Tablespace Subobject Obj. Physical
Owner Name Object Name Name Type Reads %Total
---------- ---------- ------------------------- ---------- ----- ------------ -------
INFORM INTSYS_IND SYS_LOB0000155024C00002$$ LOB 6,244,992 85.65
Оказалось, что он принадлежит $R таблице индекса Oracle text и занимает 100 МБ
SQL> SELECT
owner "Owner",
table_name "Table",
column_name "Column",
segment_name "Segment",
index_name "Index"
FROM dba_lobs
WHERE segment_name = 'SYS_LOB0000155024C00002$$';
Owner Table Column Segment Index
---------- ------------------------------ ---------- ------------------------------ ------------------------------
INFORM DR$ИНТ_ПУБЛ_ИНФ_CTXSYS$R DATA SYS_LOB0000155024C00002$$ SYS_IL0000155024C00002$$
SQL> SELECT TRUNC(SUM(bytes)/1024/1024) "Size (MB)"
FROM dba_segments
WHERE segment_name = 'SYS_LOB0000155024C00002$$';
Size (MB)
----------
104
Решил положить это хозяйство в KEEP Pool, и руководствуясь этим
Pre-Loading Oracle Text indexes into Memory , выполнил
SQL> ALTER TABLE INFORM.DR$ИНТ_ПУБЛ_ИНФ_CTXSYS$R STORAGE (BUFFER_POOL KEEP) MODIFY LOB (DATA) (STORAGE (BUFFER_POOL KEEP));
Table altered.
SQL>create or replace procedure inform.loadAllDollarR (idx_name varchar2) is
v_idx_name varchar2(30) := upper(idx_name);
type c_type is ref cursor;
c2 c_type;
s varchar2(2000);
b blob;
buff varchar2(100);
siz number;
off number;
cntr number;
begin
for c1 in (select table_name t from user_tables
where table_name like 'DR$'||v_idx_name||'%$R') loop
dbms_output.put_line('loading from table '||c1.t);
s := 'select data from '||c1.t;
open c2 for s;
loop
fetch c2 into b;
exit when c2%notfound;
siz := 10;
off := 1;
cntr := 0;
if dbms_lob.getlength(b) > 0 then
begin
loop
dbms_lob.read(b, siz, off, buff);
cntr := cntr + 1;
off := off + 4096;
end loop;
exception when no_data_found then
if cntr > 0 then
dbms_output.put_line('4K chunks fetched: '||cntr);
end if;
end;
end if;
end loop;
end loop;
end;
/
Procedure created.
SQL>exec inform.LoadAllDollarR('ИНТ_ПУБЛ_ИНФ_CTXSYS');
loading from table DR$ИНТ_ПУБЛ_ИНФ_CTXSYS$R
4K chunks fetched: 24629
PL/SQL procedure successfully completed.
Процедура радостно отрапортовала, что прочитала 96 Mb, но в KEEP пуле я вижу почему-то только сотню килобайт:
SQL> SELECT d.object_name, d.object_type, d.subobject_name,
2 count(*) blk_cnt, ROUND(count(*) * kcbwds.blk_size/1024) "SIZE (КB)"
3 FROM x$kcbwds kcbwds,
4 (SELECT lo_setid, hi_setid FROM v$buffer_pool
5 WHERE name = 'KEEP') setds,
6 x$bh bh,
7 dba_objects d
8 WHERE set_id BETWEEN setds.lo_setid AND setds.hi_setid
9 AND bh.set_ds = kcbwds.addr
10 AND d.data_object_id = bh.obj
12 AND d.object_name = 'SYS_LOB0000155024C00002$$'
13 GROUP BY d.object_name, d.object_type,d.subobject_name, kcbwds.blk_size;
OBJECT_NAME OBJECT_TYP SUBOBJECT_NAME BLK_CNT SIZE (КB)
------------------------------ ---------- -------------------- ---------- ---------
SYS_LOB0000155024C00002$$ LOB 12 96
1 row selected.
При этом в DEFAULT пуле этого сегмента нет вообще. Размера KEEP достаточно. В чем может быть дело, есть идеи?