Wie soll ich den Speicher für diese Tabelle optimieren?

7

Ich verwende MySQL, um eine Basistabelle dieses Formats zu speichern:

    id      int(11)          //Auto-Incrementing ID
    data    varchar(5120)    //Random input data, compressed by a program, not mysql.
    -----------------------
    Row size ø  916 B

Das ist beunruhigend, denn im Moment habe ich jeden Monat ungefähr 5.000 Datensätze, und ich möchte das besser optimieren, als am Ende einen Durchschnitt von 1 MB / 1000 Datensätzen zu erreichen.

Ich habe es ursprünglich so eingerichtet, weil ich die größeren Sets erfassen wollte, aber sie sind sehr selten, wie Sie hier in dieser Grafik sehen können:

Geben Sie hier die Bildbeschreibung ein

Link zur Grafik-API

count   n*128 bytes
+-------+----------
1       28
1       26
1       24
2       22
8       21
4       20
13      19
12      18
16      17
27      16
43      15
58      14
69      13
114     12
184     11
262     10
399     9
588     8
807     7
1224    6
1245    5
546     4
73      3
9       2
6       1
1       0

Mein Hauptanliegen hier ist, wie viel Platz ich verschwendet habe, um das hintere Ende dieses Diagramms unterzubringen, und was passiert, wenn ich am Ende noch größere Ausreißer habe? Ich muss meine Zeilengröße erneut erhöhen, wenn ungefähr 80% der Daten sehr gut in einen varchar 1024-Block passen, 1/5 der Größe dessen, was ich jetzt verwende.

Wie hätte ich dieses Ding überhaupt bauen sollen?

Inkognito
quelle

Antworten:

4

Da es bereits gebaut ist, schauen wir uns an, was Sie haben. Es gibt eine interessante Möglichkeit, Spaltendefinitionen für aktuell vorhandene Daten zu planen. Wenn der Tabellenname mydata lautet, versuchen Sie, diese Abfrage auszuführen:

SELECT data FROM mydata PROCEDURE ANALYZE ();

Dadurch werden keine Ihrer Daten angezeigt. Dadurch wird die Spalte dataselbst untersucht, Statistiken basierend auf den ersten 256 unterschiedlichen Werten berechnet (standardmäßig können Sie die Anzahl der unterschiedlichen Werte angeben) und der richtige Spaltentyp empfohlen werden, den die Tabelle haben sollte.

Solange die Tabelle MyISAM ist, sollten Sie sich nicht zu viele Gedanken über die Zeilengröße machen, da das Standardzeilenformat DYNAMISCH ist. Wenn es sich bei der Tabelle um InnoDB handelt (und ich hoffe, dass dies nicht der Fall ist), stellen Sie bitte sicher, dass die Daten nicht Teil des PRIMARY KEY sind. Ihr Clustered-Index wächst, als würde er unverdünntes MiracleGro in Ihren Garten gießen.

Möglicherweise müssen Sie die Datenspalte in Blöcke von 128 aufteilen und entweder MD5 (32-Zeichen-Ausgabe) oder SHA1 (40-Zeichen-Ausgabe) ausführen und diese MD5- oder SHA1-Ausgaben verketten und speichern. Das würde 75% des Speichers einsparen. Viel Spaß beim Versuch, diese Trennung zu codieren. Dies war nur ein weitläufiger Vorschlag aus meinem Kopf.

Möglicherweise möchten Sie auch die Sphinx-Indizierung verwenden.

RolandoMySQLDBA
quelle
2

Wenn Sie in MyISAM niemals Datensätze AKTUALISIEREN oder LÖSCHEN, benötigt ein Datensatz mit N Bytes für den Blob N + 8 Bytes in der .MYD-Datei.

Die MyISAM PK befindet sich in der .MYI-Datei. es wird ziemlich klein sein - ungefähr 11 Bytes / Zeile plus ein wenig Overhead, auf 1 KB Blöcke aufgerundet.

Wenn Sie InnoDB verwenden, ist das Layout ziemlich kompliziert. Es gibt 16-KB-Datenblöcke, die nie ganz voll sind, es gibt Blob-Extents (auch für VARCHAR), die nach 767 Bytes (je nach Version möglicherweise früher) usw. aktiviert werden. Die Extents werden in 1-MB-Blöcken zugewiesen. Planen Sie durchschnittlich 2N Bytes pro Zeile ein.

Die InnoDB PK wird mit den Daten gespeichert und ist daher oben vollständig enthalten. Und da AUTO_INCREMENT ist, sind Ihre Blöcke in der Regel relativ voll. Hinweis: Blöcke haben eine Größe von 16 KB, sodass Sie mindestens 20 pro Block haben.

Spielen Sie keine Spiele mit Ihrem eigenen Chunking. Es wird die Dinge verlangsamen, Ihren Code komplizieren usw. Die Festplatte ist billig. (Ja, es macht Spaß, solche Spiele zu spielen.)

Es sieht so aus, als würde die Hälfte Ihrer Datensätze nicht über den 767-Cutoff hinausgehen.

Nebenbei: Wenn es sich bei dem Blob um komprimierte Daten handelt, sollten Sie BLOB und nicht VARCHAR verwenden. VARCHAR nimmt CHARACTER SET-Attribute an, die Sie wirklich verbrennen würden, wenn Sie zu utf8 wechseln würden. Wenn Sie VAR-xx verwenden müssen, verwenden Sie VARBINARY.

Rick James
quelle