Oracle Text LOB Segment & KEEP Pool

ArtKuznetsov
Дата: 24.11.2009 15:16:59
Доброго времени суток всем!

Недавно обнаружил в отчете 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 достаточно. В чем может быть дело, есть идеи?
wurdu
Дата: 24.11.2009 15:26:03
Почитай про такие опции LOB Storage как CACHE / NOCACHE / CACHE READS. (NOCACHE - по дефолту).
ArtKuznetsov
Дата: 24.11.2009 15:50:48
wurdu,

Спасибо, то, что нужно!