PDA

View Full Version : Unicode - Performance weg



Seiten : [1] 2

spiceisnice
14-10-14, 14:39
Liebes Forum,

eventuell hat jemand ähnliche Erfahrungen gemacht (und ev. Lösungsansätze):

Wir stellen gerade eine klassische AS/400 RPG Standardsoftware auf JAVA Unicode um (infor MOVEX 12.5 RPG auf infor M3 13.2).

Erschreckend sind folgende Zahlen, als Beispiel:

PF mit 10MIO Datensätzen, bisherige Dateigröße 10GB, mit Unicode werden 25GB draus,
Selbe Datei mit QRY oder CPYF duplizieren, bisher runde 150MB/s (aus Joblaufzeit), in der Unicodevariante nur 60MB/s. Da wir sehr große Datenmenge in BI Tools übertragen, fürchte ich hier ähnliches Verhalten, da geht uns die Zeit dazu aus...

Wo kann man hier ansetzen? Infrastruktur ist aktuell mit Power7 6Proc, V7R1, VIOS, Partitionen, SVC und SAN mit V7000 etc....

andreaspr@aon.at
14-10-14, 14:50
Hallo,

Ohne genaueres über euer Design zu wissen ...

* Man muss nicht alle CHAR Felder in Unicode umändern wenn diese nie Sonderzeichen enthalten werden ( z. B. Felder die als Flag/Kennzeichen verwendet werden).
* VARCHAR bzw. NVARCHAR (für Unicode) kann verwendet werden. Damit sollte viel Speicher gesparrt werden können. Wichtig in diesem Fall ist den Parameter ALLOCATE richtig zu verwenden.

lg Andreas

Fuerchau
14-10-14, 14:55
Leider nur mit stärkeren Maschinen!
Unicode ist ein 2-Byte-Zeichensatz (DBCS), d.h., dass alle Zeichenfelder mit Unicode nun den doppelten Platz benötigen. Dies betrifft auch Indizes und Indexbäume. Leider halbiert sich nun auch die max. nutzbare Indexlänge von 2KB (ich weiß nicht ob sich die inzwischen vergrößert hat).
Auch die Datenlänge einer Tabelle halbiert sich da ebenso auf 16KB.

Bei QRY/400 erklärt sich das, da QRY nicht in Unicode arbeitet sondern die Daten in SBCS mit der Job-CCSID umgewandelt werden müssen. Hier kommt also die Codewandlung als Laufzeit hinzu.

Bei CPYF weiß ich nicht wie der mit Unicode umgeht. Hier ist aber im Wesentlichen entscheidend, ob beim Ziel die Indizes aktiv sind oder nicht. Hier kann man Geschwindigkeit rausholen in dem man die Indizes vor dem CPYF deaktiviert und hinterher parallel (SBMJOB in eine JOBQ für mehrere Job's) wieder aktiviert.
Auch sollte man überlegen ob ein "insert into ... select * from ..." hier nicht effektiver ist.

Auch bei der Übergabe per ODBC/JDBC verdoppeln sich natürlich die Datenmengen!
Für ODBC kann man noch die Datenkomprimierung anschalten (wenn sie noch aus sein sollte).
Ansonsten helfen da nur schnellere Leitungen (bei GBit-Netzen eher sinnlos).

Fuerchau
14-10-14, 15:07
Das mit dem Allocate würde ich mal lassen. Wenn Geschwindigkeit Vorrang hat, dann sollte man VARCHAR's nicht splitten!

Was das Wachstum von 10GB zu 25GB angeht, so vermute ich dass neben der Unicode-Umstellung ggf. noch auf VARGRAPHIC bzw. NVARCHAR umgestellt wurde.
Wie der Vorredner schon sagte, es macht keinen Sinn jedes Feld auf Unicode umzustellen oder CHAR(1) auf NVARCHAR(1). Hier würde ein NCHAR(1) schon reichen.

spiceisnice
14-10-14, 16:15
Danke für die Anworten bisher.

Das Datenbankdesign ist durch den ERP Hersteller vorgegeben, alle CHAR Felder auf GRAPHICS umgestellt. Der Größenwachstum ist ja noch beherrschbar, Problem bleibt eben die längere Datenübertragung, vor allen im BI Bereich auf Datawarehouse mit SQL Server als Ziel. QRY und CPYF sind nur einfache Beispiele um die Auswirkung rasch zu sehen, spielen in der Praxis keine Rolle.

Fuerchau
14-10-14, 17:05
Ggf. klappt es ja mit Views bzw. Casts für die BI-Welt um die Übertragungslast zu minimieren:

cast(trim(UnicodeFeld) as varchar(nn) ccsid 1208)

CCSID 1208 entspricht UTF-8.
Dies ist ja variabel zwischen 1-4 Byte, wobei eben 99,9% aller Zeichen nur 1 Byte lang ist.
Damit kann das Übertragungsvolumen ja reduziert werden.

Allerdings geht der SQL-Server (oder auch andere ODBC-Programme) nicht davon aus, UTF-8 zu bekommen sondern entweder SBCS (1252 ANSI) oder Unicode (2-byte-Code).
Für die Umwandlung UTF-8 in Unicode gibt es im SQL-Server allerdings keine Standardfunktion.
Diese müsste man als .NET-Funktion noch integrieren.

Eine Komprimierung von 2-byte-Zeichen (im ODBC-Treiber einstellbar), wobei eben bei 99,9% das 1.Byte immer x'00' ist wird nicht so effektiv sein, da solche Routinen selten auf diese Spezifika eingehen.
X'40404040' lässt sich eben besser komprimieren als x'0020002000200020'.

Für BI gibt es nur eine vernünftige Lösung:
Übertragen der Daten in die SQL-Datenbank per Update-Lösung (Scripte), so dass nur neu entstandene Daten kopiert werden müssen und nicht immer alles.

Alternativ kannst du ja auch Views erstellen, die dir für BI alles wieder auf 273 umwandeln solange du keine gemischten Daten (West-/Osteuropa) hast.

Und vielleicht ist ja alles gar nicht so schlimm.

andreaspr@aon.at
15-10-14, 07:58
Das mit dem Allocate würde ich mal lassen. Wenn Geschwindigkeit Vorrang hat, dann sollte man VARCHAR's nicht splitten!

Eigentlich ist es genau umgekehrt. Wenn kein Allocate angegeben wird, werden IMMER die Werte außerhalb des Satzes gespeichert. Somit müssen zusätzliche I/Os durchgeführt werden um die Werte der Spalten zu bekommen.
Mit dem ALLOCATE Parameter kann definiert werden ab wieviel Zeichen erst der zu speichernde Wert ausgelagert werden soll.
Beispiel:
Wenn also der Großteil der Werte einer Spalte nicht mehr als 20 Zeichen beinhalten und die Spalte mit VARCHAR(200) definiert wurde, macht es zwecks Performance Sinn ein ALLOCATE(20) zu definieren.
Somit bleiben die vielen kleineren Werte zusammen im gleichen Speicherbereich wie der Satz selber und man erspart sich viele I/Os dadurch.

alfredo
15-10-14, 08:36
Angeblich gibt es minimum-Allocate von 32 Bytes, die das System immer nimmt.
(Wahrscheinlich weil, viele das Allocate vergessen)

Speziell bei Kommentarfeldern mach Varchar Sinn.
Beispiel möglicher Kommentar 500 Zeichen, es wird aber nur bei 1% ein Kommentar erfasst.

Bei Zuweisung in RPG ist ein %trim empfehlenswert.
Man kann das mit SQL mit Length(Feld) bei besetehenden Daten überprüfen.

Bei uns ist auch der Trend Richtung Unicode.
Das ist natürlich für Joins problematisch, wenn manche Dateien umgestellt sind, andere nicht.

BenderD
15-10-14, 08:50
... ist doch interessant, dass beim Thema Performance immer wieder die Mythen dominieren:
- varchar und allocate: Angabe von Allocate < Feldlänge spart Platz und wird mit zusätzlichem synchronem I/O bestraft, wenn die belegte Feldlänge > alls der allocate ist. Das lesen von "Luft" ist asynchroner I/O und kann wg. pre paging vernachlässigt werden.
- VARCHAR allgemein: Verwendung von VARCHAR ist verbreiteter Standard außerhalb von DB2, die AS/400 Implementierung ist lausig und ich würde das eher vermeiden, wenn nicht Datenbank Unabhängigkeit gefordert ist.
- Unicode: was die Positionierung der AS/400 angeht ähnlich wie VARCHAR, aber "wat mutt dat mutt"
- Keyfelder: Keyfelder sollten immer Binary sein (Integer oder CCSID 65535), niemals VARCHAR (eine verbreitete Oracle Sitte) - ansonsten können unterschiedliche Keys je nach Einstellungen des Bildschirms gleich aussehen (das ist also kein Performance Problem).

D*B

Fuerchau
15-10-14, 08:57
Laut Doku (SQL-Handbuch) gehört die IBM diesbezüglich tatsächlich erschlagen!

Schaut man sich den Callstack mal so an, dann ist die letzte Ebene beim File-IO immer QDBPUT/QDBGET.
Bei Native-IO genauso wie bei SQL.
Beim Lesen wird also immer der gesamte Datensatz bereitgestellt, beim Schreiben der gesamte Datensatz erwartet. Zusätzlich gilt immer noch die Regel, dass die Satzlänge (ohne LOB's) ja max. 32KB ist.
Also muss ich im Umkehrschluss alle VARCHAR's mit ALLOCATE(Defined-Size) definieren damit diese eben im Satzbereich und nicht extra gespeichert werden.
Platz sollte hier nicht ausschlaggebend sein.

Die IBM sollte den Default für ALLOCATE irgendwie so setzen können, dass dies immer gilt.
Man bedenke, dass beim Lesen immer die gesamte Datenzeile zur Verfügung gestellt wird. Also zusätzliche IO's für den Varchar-Bereich immer durchgeführt werden.
SQL entnimmt dann die benötigten Variablen aus diesem Puffer bzw. stellt sie beim Update dort hin.
RPG/LE macht dies genauso, in dem die verwendeten Felder per Move aus dem Puffer in die Variablen übertragen werden (auch wenn eine DS definiert ist!) und beim Update wieder zurück.
COBOL arbeitet direkt mit dem IO-Puffer.

Fazit:
Wenn also Performance gewünscht wird, so muss man bei Create Table / CRTPF für Varchar/Nvarchar die Allocate-Klausel auf das Maximum setzen!