Rebuild einer Tabelle mit einer LONG RAW Spalte

Bei einem Kunden trat das Problem auf, dass das Auslesen einer kleinen Tabelle (25 Zeilen mit 4 Spalten) durchschnittlich über 45 Sekunden (!) dauerte. Nach kurzer Analysze war das Problem <!–more–> klar: Die Tabelle war mal sehr groß gewesen und hatte jetzt nur noch Zeilen im ersten und im letzten Block. Dazwischen lagen ca. 4 GB allokierter, aber ungenutzter Speicher, der bei jedem Lesen überlesen werden musste.

Natürlich war die erste Idee, die Tabelle zu reorganisieren:

ALTER TABLE SMALLTAB move;

Leider hatte diese Tabelle jedoch eine LONG RAW Spalte, so dass dieses Kommando mit dem Fehler

ORA-00997: illegal USE OF LONG datatype

fehlschlug.

Da die LONG RAW Spalten nicht sehr groß waren (die Längen waren überall kleiner als 20.000 Zeichen), konnten wir das Problem in diesem Fall mit Hilfe eines kleinen PL/SQL Programms lösen. Wäre eine oder mehr Spalten länger als 32.767 Zeichen gewesen, hätten wir die Tabellen exportieren, mit TRUNCATE leeren und anschließend wieder importieren müssen.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# Umbenennen der alten
ALTER TABLE SMALLTAB RENAME TO SMALLTAB_OLD;
 
# Anlegen einer neuen
CREATE TABLE SMALLTAB( 
  id                NUMBER NOT NULL
 ,TYPE              NUMBER NOT NULL
 ,record            long raw NOT NULL
);
 
# Füllen der neuen Tabelle mit den Werten aus der alten
SET serveroutput ON
DECLARE
  v_txt VARCHAR(32767 CHAR);
  i     NUMBER              := 0;
BEGIN
  FOR r IN (SELECT id, TYPE, record FROM SMALLTAB_OLD) loop
    i := i + 1;
    v_txt := UTL_RAW.CAST_TO_VARCHAR2(r.record);
    dbms_output.put_line('Row='||i||': '||LENGTH(v_txt));
 
    INSERT INTO SMALLTAB(id,TYPE,record)
    VALUES (r.id, r.type, utl_raw.cast_to_raw(v_txt));
  END loop;
 
  commit;
END;
/
 
# die alte droppen
DROP TABLE SMALLTAB_OLD;