Deutliche Reduzierung der Satzanzahl einer Tabelle mit Text und BYTE im Tablespace
(Beitrag von CURSOR Mitarbeiter Andreas Seifert)
Normalerweise sind die Limitierungen für Tabellen in einer Informix-Instanz ausreichend hoch, so das man keine Probleme beim Betrieb der Instanz bekommt. Nutzt man die alten Simple Large Objects TEXT und BYTE in Informix ist das aber anders. Diese BLOBs können noch nicht in einem Smart-Blobspace liegen, wie die neuen Smart Large Objects sondern müssen in einen Blobspace (alter Typ).
Im Gegensatz zu Smart-Blobspaces können Blobspaces aber nicht mit Logging angelegt werden. Das hat große Nachteile, wenn man eine Hochverfügbarkeitslösung wie HDR, RSS oder SDS nutzen möchte. Da alle diese Lösungen über den Austausch von logical Log-Informationen funktionieren, werden Objekte die nicht über das log. Log laufen nicht repliziert.
Die einzige Lösung, die Simple Large Objects mit log. Log zu betreiben ist, auf einen Blobspace zu verzichten und die BLOBs in den Tablespace zu speichern.
Jetzt kommen aber die die Tabellen-Limits von Informix zum Tragen. Eine Row darf 32kByte lang werden. Das ist in diesem Fall kein problematisches Limit, weil für ein Simple Large Object in die Row-Size nur ein Descriptor von 56Byte eingeht. Ein weiteres Limit, die maximale Anzahl Pages pro Fragment, ist hier wesentlich tragischer. Dieses Limit liegt nämlich bei 16.777.215 Daten-Pages. Die Frage ist, zählen die Pages, die ein Simple Large Object belegt dazu?
Die Dokumentation von Informix schweigt hierzu. Um zu ermitteln, ob die Blob-Pages zu den Daten-Pages zählen, haben wir ein 100GB großen Chunk angelegt. Plattform war Windows mit 4k Pagesize. In einer Schleife wurden in die Tabelle mit 2 Feldern vom Typ TEXT Sätze mit durchschnittlich 300kByte an Daten eingefügt. Die Frage war - bei wieviel Sätzen ist Schluß?
create table "informix".testtableSchema der Testtabelle
(
f01 char(64) not null ,
f02 char(4),
f03 char(30),
f04 char(2),
f05 char(1),
f06 char(5),
f07 char(5),
f08 char(1),
f09 text ,
f10 text ,
f11 char(8),
f12 date,
f13 date
);
Wenn die Blob-Pages zu den Daten-Pages zählen, so sollten wir an das Page-Limit stoßen. Die Anzahl Sätze die man erreichen kann berechnet sich wie folgt:
300kByte Daten pro Satz / 4kByte Pagesize = 75 Pages pro Satz
Limit für Pages pro Fragment 16.777.215 / 75 Pages pro Satz = 223.696,2 Sätze
In diesem Fall ist zu erwarten, das bei ca. 223.696 Sätzen ein Fehler auftritt. So kam es auch. Das load-Script meldete nach einer Weile auch folgenden Fehler bei 222493 Sätzen:
D: mp est>dbaccess testdb loadFehlermeldung des dbaccess beim load der Daten
Database selected.
605: Cannot write blob. 136: ISAM error: no more extents
847: Error in load file row 1.
Error in line 2
Near character position 52
Database closed.
Das klingt erst einmal irreführend, denn nach Prüfung der Tabelle hatte diese nur 7 Extents. Die Fehlermeldung ISAM 136 hat aber mehrere Bedeutungen. Im ausführlichen Fehlertext steht, man soll ein onstat -t ausführen und die Ausgabe betrachten:
IBM Informix Dynamic Server Version 12.10.FC3 -- On-Line -- Up 1 days 00:37:15 -- 74880 KbytesAusgabe des onstat -t
Tblspaces
n address flgs ucnt tblnum physaddr npages nused npdata nrows nextns
.
.
.
. 1010 8135d030 0 1 500001 5:4 50 6 0 4 1
1015 81369030 2 1 600001 6:4 50 4 0 0 1
1016 811e3030 0 1 700001 7:4 100 70 0 68 2
1017 811e3ae0 0 1 700002 7:5 8 6 3 71 1
1018 8119c030 0 1 700003 7:6 16 12 6 557 1
1019 81213030 0 1 700004 7:7 64 43 38 114 1
1028 81452030 0 1 70000d 7:16 8 3 0 0 1
1032 81857030 0 1 700011 7:20 128 70 53 513 5
1046 8185b030 0 1 70001f 7:34 8 3 0 0 1
1067 81933060 0 1 700034 7:511 8 3 0 0 1
1074 81902980 0 1 70003b 7:518 8 2 0 0 1
1082 81830680 2 1 700043 7:526 16777215 16777215 13906 222493 7
1083 81927030 40000002 1 700044 7:527 384 280 0 0 8
1084 8121aa70 40000002 1 700045 7:528 384 278 0 0 8
76 active, 1084 total
Folgender Satz aus dem Fehlertext:
"If nused is close to 0xFFFFFF (16,777,215), the maximum number of pages has been reached for the table. Reallocate the table in a dbspace with a larger page size as described above."
zeigt, das hier das Page-Limit für das Tabellenfragment erreicht wurde.
Schöner zusammengefasst zeigt ein oncheck -pT testdb:testtable den Zustand:
TBLspace Report for testdb:informix.testtableAusgabe des oncheck -pT testdb:testtable
Physical Address 7:526
Creation date 06/26/2014 09:59:08
TBLspace Flags c01 Page Locking
TBLspace contains TBLspace BLOBs
TBLspace use 4 bit bit-maps
Maximum row size 240
Number of special columns 2
Number of keys 0
Number of extents 7
Current serial value 1
Current SERIAL8 value 1
Current BIGSERIAL value 1
Current REFID value 1
Pagesize (k) 4
First extent size 8
Next extent size 2097152
Number of pages allocated 16777215
Number of pages used 16777215
Number of data pages 13906
Number of rows 222493
Partition partnum 7340099
Partition lockid 7340099
Extents
Logical Page Physical Page Size Physical Pages
0 7:1271 65536 65536
65536 7:66815 262144 262144
327680 7:328975 589824 589824
917504 7:918831 917504 917504
1835008 7:1836399 2359296 2359296
4194304 7:4195823 4194304 4194304
8388608 7:8390383 8388607 8388607
TBLspace Usage Report for testdb:informix.testtable
Type Pages Empty Semi-Full Full Very-Full
---------------- ---------- ---------- ---------- ---------- ----------
Free 59
Bit-Map 2065
Index 0
Data (Home) 13906
TBLspace BLOBs 16761185 0 184 352182 16408819
----------
Total Pages 16777215
Unused Space Summary
Unused data slots 3
Unused bytes per data page 164
Total unused bytes in data pages 2280584
Unused bytes in TBLspace Blob pages 456503339
Home Data Page Version Summary
Version Count
0 (current) 13906
Hier sieht man auch, das die Tabellendaten nur 13.906 Pages verbrauchen und der gesamte Rest die Blobpages sind.
Etwas versteckt findet man die passenste Fehlermeldung in der Datei $DBTEMP/$INFORMIXSERVER.alarm. Dort steht:
2014-06-26 12:22:19 WARNING: partition 'testdb:informix.testtable': no more pages
Zeile aus der Date $DBTEMP/$INFORMIXSERVER.alarm
Diese Meldung besagt genau das, was passiert ist. Man hat das Limit der Pages einer Partition erreicht. Leider fehlt diese Meldung in den Log-Dateien, in die man in erster Linie schaut um Probleme zu erkennen. Hat man die automatische Alarmierung im Alarmprogramm aktiviert, bekommt man sie aber als Mail.
Stößt man an diese Grenze, gibt es verschiedene Lösungen:
1. Man verlegt die Tabelle in einen DBSpace mit größerer Pagesize
Wenn man sich die Berechnung ansieht gewinnt man hier bei Verdopplung der Pagesize nur knapp das Doppelte der Sätze. Die maximale Pagesize berägt 16k, was in unserem Beispiel nur ca. 890.000 Sätze bedeutet.
2. Man nutzt die Fragmentierung
Hiermit läßt sich dieses Problem leicht lösen. Ich kann 2047 DBSpaces haben, Fragmentieren geht auch innerhalb eines DBSpaces schon, so das man hier nicht mehr an das Limit stößt.
Der Nachteil dieser Lösung: Fragmentierung ist nur in der Enterprise / Advanced Enterprise - Edition erlaubt. Alle anderen Editionen dürfen die Fragmentierung nicht nutzen.
3. Man nutzt Smart Large Objects
Diese Lösung bietet sich an, Smart Large Objects kann ich in Smart-Blobspaces legen, bei denen ich wählen kann, ob der Space mit oder ohne log. Log läuft. Allerdings ist das Handling der Smart Large Objects in der Anwendungsentwicklung abweichend von dem der Simple Large Objects. Es kann sich hierbei ein hoher Aufwand bei der Umstellung der Applikation ergeben oder man nutzt nur eine gekaufte Anwendung und ist gar nicht in der Lage eine solche Umstellung zu machen.
Leider kann man sich hier nicht mit einer View behelfen, die die Smart Large Objects entsprechend casted, weil die IBM zwar einen Cast von TEXT nach CLOB und BYTE nach BLOB eingebaut hat, aber nicht für den umgekehrten Weg.
Diese Lösung wäre nur mit einer selbstgeschriebenen UDR möglich, die eine Umsetzung von TEXT in CLOB oder BYTE in BLOB in beide Richtungen ermöglicht.
Dipl. Wirtschaftsinformatiker Andreas Seifert
(Geschäftsbereich IBM Distribution)
CURSOR Software AG
Friedrich-List-Straße 31
D-35398 Gießen