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; |