MySQL: Index für 1,4 Milliarden Datensätze erstellen


9

Ich habe einen Tisch mit 1,4 Milliarden Datensätzen. Die Tabellenstruktur ist wie folgt:

CREATE TABLE text_page (
    text VARCHAR(255),
    page_id INT UNSIGNED
) ENGINE=MYISAM DEFAULT CHARSET=ascii

Die Anforderung besteht darin, einen Index über der Spalte zu erstellen text.

Die Tischgröße beträgt ca. 34G.

Ich habe versucht, den Index mit der folgenden Anweisung zu erstellen:

ALTER TABLE text_page ADD KEY ix_text (text)

Nach 10 Stunden Wartezeit gebe ich diesen Ansatz endlich auf.

Gibt es eine praktikable Lösung für dieses Problem?

UPDATE : Es ist unwahrscheinlich, dass die Tabelle aktualisiert, eingefügt oder gelöscht wird. Der Grund für die Erstellung eines Index für die Spalte textliegt darin, dass diese Art von SQL-Abfrage häufig ausgeführt wird:

SELECT page_id FROM text_page WHERE text = ?

UPDATE : Ich habe das Problem durch Partitionieren der Tabelle gelöst.

Der Tisch ist in 40 Teile auf einer Säule unterteilt text. Das Erstellen des Index für die Tabelle dauert ungefähr 1 Stunde.

Es scheint, dass die Erstellung des MySQL-Index sehr langsam wird, wenn die Tabellengröße sehr groß wird. Durch die Partitionierung wird die Tabelle in kleinere Amtsleitungen aufgeteilt.


1
Was ist falsch an der normalen CREATE INDEXAnweisung?

Ich würde vorschlagen, dass diese Frage bei ServerFault besser geeignet ist - es handelt sich eher um einen DB-Administrator als um eine Programmierfrage.
dort

@Derk: Der normale CREATE INDEX-Ansatz ist zu langsam. Ich muss die Aufgabe innerhalb eines Tages erledigen.

1
Hmm ... ich glaube nicht, dass du das umgehen kannst. Zum Erstellen des Index muss das DBMS alle Datensätze durchsuchen, ihre "Text" -Felder erfassen und die entsprechenden Baumknoten / Teilbäume einfügen / ändern. Und das braucht viel Zeit für 34G ...
Chiccodoro

Wie viel Speicher hat Ihr DB-Server? Haben Sie MySQL so konfiguriert, dass es den gesamten Speicher verwendet, oder beschränkt es sich selbst?

Antworten:


4

Könnte es sein, dass Ihr System der Aufgabe einfach nicht gewachsen ist? Ich verwende MySQL (hier SQL Server) nicht, aber ich kenne den Schmerz, eine 800-Millionen-Eintragstabelle zu indizieren. Grundsätzlich ... benötigen Sie dafür die richtige Hardware (wie in: viele schnelle Discs). Ich benutze jetzt fast ein Dutzend Velociraptoren und die Leistung ist großartig;)

SQL Server (nicht als MS SQL Server, sondern als Datenbankserver, die SQL verwenden) leben und sterben mit Datenträgerzugriff, und normale Datenträger sind für größere Vorgänge einfach nicht geeignet.


Mein Zweifel ist, dass die Indexerstellung normalerweise sehr schnell ist, wenn die Anzahl der Datensätze gering ist. sagen wir Millionen. Aber wenn die Zählung bei Milliarden liegt, wird die Indexerstellung so langsam. Das Zeitwachstum scheint exponentiell zu sein.

Sollte eigentlich nicht sein. MySQL hat im Allgemeinen Grenzen, aber es ist keine Mistdatenbank, und das wäre SEHR schlecht. Die Indexgenerierung wird langsamer, aber durch log (n), nicht (n), also sollte es nicht wirklich so schlimm sein.
TomTom

4

Möglicherweise möchten Sie einen Index für die ersten (z. B. 10) Zeichen des Textfelds erstellen.

Aus den Dokumenten:

Es können Indizes erstellt werden, die nur den führenden Teil der Spaltenwerte verwenden. Dabei wird die Syntax col_name (length) verwendet, um eine Indexpräfixlänge anzugeben:

CREATE INDEX ix_text ON text_page (text(10))

4

Ich habe das Problem durch Partitionieren der Tabelle gelöst.

Der Tisch ist in 40 Teile auf einer Säule unterteilt text. Das Erstellen des Index für die Tabelle dauert ungefähr 1 Stunde.

Es scheint, dass die Erstellung des MySQL-Index sehr langsam wird, wenn die Tabellengröße sehr groß wird. Durch die Partitionierung wird die Tabelle in kleinere Amtsleitungen aufgeteilt.


40 x 1 Stunde ist also weniger als 10 Stunden?
Symcbean

3

Setzen Sie sort_buffer_size auf 4 GB (oder wie viel Sie können, je nachdem, wie viel Speicher Sie haben).

Im Moment führt der Erstellungsindex eine Sortierung durch, aber da Sie eine sort_buffer_size von 32 MB haben, wird die Festplatte im Grunde genommen unnötig überlastet.


Diese Beiträge stimmen so gut wie nicht mit Ihnen überein : xaprb.com/blog/2010/05/09/how-to-tune-mysqls-sort_buffer_size und besser ronaldbradford.com/blog/… Es klingt so, als wäre das kein globaler Wert pro Abfrage, das sind also 4 GB pro Abfrage, die Sie empfehlen. Wenn es 256 KB überschreitet, wird es auf die Festplatte abgebildet, anstatt der tatsächliche In-Memory-Speicher zu sein. Wenn Sie es klein halten, sind mehrere Durchgänge erforderlich, es wird jedoch die Festplatte vermieden (es wird nicht getauscht).
Ry4an Brase

3

Wenn Sie keine Fragen stellen müssen wie:

SELECT page_id FROM text_page WHERE text LIKE '?%';

Ich würde vorschlagen, eine neue Hash-Spalte zu erstellen und die Tabelle nach Spalten zu indizieren. Die Gesamtgröße der Tabelle + des Index ist möglicherweise viel kleiner.

UPD : Übrigens belegen 1,4 Milliarden Ganzschlüssel-Ganzzahlen etwa 6 GB, dh die durchschnittliche Länge der Zeichenfolge beträgt weniger als 30 Zeichen. Eine Indizierung nach einem Präfix ist möglicherweise vorzuziehen.

Sie sollten sich auch die MERGE Storage Engine ansehen .


2

Eine Möglichkeit, dies zu tun, besteht darin, eine neue Tabelle mit dem eingestellten Index zu erstellen und die Daten in die neue Tabelle zu kopieren.

Stellen Sie außerdem sicher, dass Sie genügend temporären Speicherplatz haben.


1
Ich habe diesen Ansatz versucht. Nach 10 Stunden wurden weniger als 1% der Daten in die neue Tabelle kopiert.

1
Alter ... es sind 1,4 Milliarden Rekorde. Nicht Millionen, Milliarden. Das ist viel. Trotzdem wird es eine Weile dauern.

Wenn Sie sich für diese Methode entscheiden, teilen Sie die Kopie in kleinere Teile auf. Sagen wir ungefähr 100 bis 200 Millionen für jede Kopie.

1
@ dekompiliert, es in kleinere Stücke zu zerlegen, wird nichts bewirken (tatsächlich könnte es weniger effizient sein). @Bryan, selbst mit 1,4 Milliarden Datensätzen sollte es nicht 1.000 Stunden dauern.

0

Für den Fall, dass Sie sich immer noch fragen, wie Sie dies am besten tun können, würde ich Ihnen empfehlen, ein Online-Tool zum Ändern von Tabellen zu verwenden.

Es gibt viele davon im Internet, eine der bekanntesten ist:

Wir haben die gleichen Probleme mit großen Tischen (mehr als 500mil Datensätze) und die Änderung geht perfekt. Es erstellt eine neue tmp-Tabelle, fügt der ursprünglichen Tabelle einen Trigger hinzu (für die neuen Datensätze zum Aktualisieren / Löschen / Einfügen) und kopiert in der Zwischenzeit alle Datensätze in die neue Tabelle (mit der neuen Struktur).

Viel Glück!

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.