Zusammenfassung: Welche Methode sollte für die MySQL JDBC-Extraktion verwendet werden? Ich erkläre es Ihnen. Ich wurde kürzlich bei einem Migrationsprojekt in der Cloud vom MySQL-Extraktionsmodus gequält. Zunächst wurden wir von Kunden wegen Speicherüberlaufs kritisiert, und dann erneut wegen der geringen Migrationseffizienz. Welche Methode sollte für die MySQL JDBC-Extraktion verwendet werden? Ich erkläre es Ihnen. 1.1 Java-JDBC-KommunikationsprinzipienDie Kommunikation zwischen JDBC und der Datenbank erfolgt über Socket. Der allgemeine Vorgang ist in der folgenden Abbildung dargestellt. Mysql-Server -> Kernel Socket Buffer -> Client Socket Buffer -> JVM, wo sich JDBC befindet 1.2 Drei Modi zum Lesen von JDBC-Daten1.2.1 Methode 1: Daten mit JDBC-Standardparametern lesenEs gliedert sich im Wesentlichen in folgende Schritte: 1) Der MySQL-Server schreibt Daten über OuputStream in den lokalen Kernelpuffer des Socket-Servers. Dies ist eine Speicherkopie. 2) Wenn sich Daten im lokalen Kennel-Puffer des Socket-Servers befinden, werden die Daten über die TCP-Verbindung in den Kennel-Puffer des Computers übertragen, auf dem sich der Socket-Client befindet. 3) Die JVM, in der sich JDBC befindet, verwendet InputSream, um lokale Kennel Buffer-Daten in den JVM-Speicher zu lesen. Wenn keine Daten vorhanden sind, wird das Lesen blockiert. Der nächste Schritt besteht darin, den Vorgang 1, 2, 3 kontinuierlich zu wiederholen. Das Problem besteht darin, dass die JVM des Socket-Clients im Standardmodus den Kennel Buffer liest, ohne die Größe des lokalen Speichers zu berücksichtigen und so viel wie möglich liest. Wenn die Daten zu groß sind, führt dies zu einer FULL GC, gefolgt von einem Speicherüberlauf. Siehe die JDBC-API-Dokumente. Der Java-Democode im Standardmodus lautet wie folgt 1.2.2 Methode 2: CursorabfrageUm das Speicherüberlaufproblem in Methode 1 zu lösen, stellt JDBC einen Cursorparameter bereit. Fügen Sie beim Herstellen einer JDBC-Verbindung useCursorFetch=true hinzu. Nach dem Setzen des Cursors teilt JDBC dem Server jedes Mal die zu extrahierende Datenmenge mit, um einen Speicherüberlauf zu vermeiden. Der Kommunikationsvorgang ist in der folgenden Abbildung dargestellt. Obwohl die Cursorabfrage mit Methode 2 das Problem des Speicherüberlaufs löst, ist Methode 2 stark von der Netzwerkqualität abhängig. Wenn die Netzwerkverzögerung zunimmt und man davon ausgeht, dass jede Kommunikation um 10 ms zunimmt, dauern 100.000 Kommunikationen 1.000 Sekunden länger. Hier ist nur die RT jeder Anforderung. Jedes Mal, wenn TCP eine Nachricht sendet, erfordert es eine Rückmeldung ACK, um die Datenzuverlässigkeit sicherzustellen. Jedes Mal, wenn der Client 100 Zeilen abruft (die Anzahl der angeforderten Zeilen ist konfigurierbar), finden mehrere Kommunikationen statt, was das durch die erhöhte Latenz verursachte Effizienzproblem noch weiter verschärft. Darüber hinaus kann MySQL bei Cursorabfragen die Endverzögerung der Abfrage nicht vorhersagen. Um mit seinen eigenen DML-Operationen fertig zu werden, erstellt es lokal einen temporären Speicherplatz zum Speichern der zu extrahierenden Daten. Daher treten während der Cursorabfrage die folgenden Phänomene auf: a. Die IOPS steigen sprunghaft an. Mysql schreibt während der Datenübertragung Daten in den temporären Speicher und liest Daten aus dem temporären Speicher, was eine große Anzahl von IO-Operationen auslöst. b. Der Speicherplatz nimmt rapide zu. Der Lebenszyklus des temporären Speicherplatzes besteht während der gesamten JDBC-Lesephase und wird von MySQL erst dann zurückgefordert, wenn der Client Result.close() initiiert. c. CPU und Speicher erhöhen sich um einen bestimmten Prozentsatz. Informationen zu den Prinzipien der Cursorabfrage finden Sie im Blog „MySQL JDBC StreamResult Communication Principle Analysis and JDBC source code“, das in diesem Artikel nicht wiederholt wird. In den JDBC-API-Dokumenten finden Sie den Java-Democode für den Cursormodus wie folgt 1.2.3 Methode 3: Daten aus dem Stream lesenMethode 1 führt zu einem JVM-Speicherüberlauf. Obwohl Methode 2 keine vollständige GC verursacht, ist die Kommunikationseffizienz gering und führt außerdem dazu, dass die IOPS des Mysql-Servers in die Höhe schnellen und Speicherplatz verbrauchen. Daher führen wir Stream zum Lesen von Daten ein. Der Stream muss vor dem Lesen des Ergebnisses festgelegt werden Bei Methode 3 wird vor der Kommunikation keine Server-Client-Interaktion durchgeführt, wodurch eine geringe Kommunikationseffizienz vermieden wird. Der Server bereitet Daten vor und schreibt sie in den Kennel-Puffer des Servers. Diese Daten werden über die TCP-Verbindung an den Kennel-Puffer des Clients übertragen. Anschließend wird die Methode inputStream.read() des Clients aktiviert, um die Daten zu lesen. Anders als bei Methode 1 liest der Client nur Daten in der Größe eines Pakets auf einmal. Wenn ein Paket nicht mit einer Zeile voll ist, wird ein weiteres Paket gelesen. Wenn der Client Daten langsamer verbraucht als die Datenübertragungsrate, sind die Daten im Zwingerbereich auf der Clientseite voll, und dann sind auch die Zwingerdaten auf der Serverseite voll, wodurch OuputStream blockiert wird. Auf diese Weise ist JDBC im Stream-Modus wie eine Wasserleitung, die zwei Reservoirs verbindet, und Client und Server erreichen ein Gleichgewicht. Da für den JDBC-Client jedes Mal Daten aus dem Zwinger gelesen werden, ist die Effizienz viel höher als bei Methode 2 und das Lesen einer kleinen Datenmenge jedes Mal führt nicht zu einem Überlauf des JVM-Speichers. Für den Server schreibt Mysql jedes Mal Daten in den Zwinger. Es muss kein temporärer Speicherplatz erstellt werden, es sind keine E/A-Lesvorgänge erforderlich und auch der Druck auf den Server wird verringert. Natürlich bringt Methode 3 auch ihre eigenen Probleme mit sich, wie etwa die Unfähigkeit, beim Streaming abzubrechen, und die nicht blockierende Natur des Abbruchs. Siehe die JDBC-API-Dokumente. Viele Online-Tutorials erfordern die Einstellung von useCursorFetch=trueResultSet.FETCH_REVERSE usw. Tatsächlich stellte der Editor nach dem Studium des JDBC-Treiberquellcodes fest, dass nur fetchSize=Integer.MIN_VALUE eingestellt werden muss und andere Konfigurationen mit der Standardkonfiguration übereinstimmen. Der Java-Democode für den Cursormodus lautet wie folgt 1.3 Optimierung des Cloud Data Migration Service in drei ModiCloud Data Migration (CDM) ist ein Migrationstool für Huawei Cloud. Weitere Einzelheiten finden Sie auf der offiziellen CDM-Website. Der Editor zeigt anhand von CDM, wie Sie zum Extrahieren von Daten zwischen drei Modi wechseln. CDM verwendet standardmäßig Modus 3, also die Streaming-Datenextraktion. Wenn Sie zu Modus 1 wechseln müssen, ist eine zusätzliche Konfiguration für Modus 2 erforderlich. 1.3.1 Konfigurationsmethode 1: StandardablesungErstellen Sie einen neuen Mysql-Connector. Einzelheiten zur Erstellung finden Sie auf der offiziellen Website. Fügen Sie in den erweiterten Eigenschaften useCursorFetch=false und adopt.stream=false hinzu. 1.3.2 Konfigurationsmethode 2: CursorabfrageBearbeiten Sie den MySQL-Connector und fügen Sie in den erweiterten Eigenschaften useCursorFetch=true und adopt.stream=false hinzu. Die Größe der Cursorabfrage kann über die Abrufgröße auf der Schnittstelle angepasst werden, der Standardwert ist 1000. 1.3.3 Konfigurationsmethode 3: Streaming CDM verwendet standardmäßig den Streaming-Modus und es ist keine zusätzliche Konfiguration erforderlich. Beachten Sie, dass im Stream-Modus 1.3.4 LeistungsvergleichErstellen Sie einen CDM-Migrationsjob für Mysql2Hive. Die Quelltabelle hat 101 Felder und 1 Million Datenzeilen. Die Konfiguration ist wie folgt: Methode 1: Das Schreiben von 1 Million Datenzeilen dauert 1 Minute und 22 Sekunden. Methode 2: Schreiben Sie auch 1 Million Zeilen, passen Sie fetchSzie jeweils auf 1, 10, 100, 100 an und der Mindestzeitaufwand beträgt 2m1s Methode 3: Schreiben Sie auch 1 Million Zeilen und benötigen Sie 1m5s Der Editor testete auch eine kleine Tabelle mit 1 Million Elementen. Es ist offensichtlich, dass die Geschwindigkeit von Methode 1 und Methode 3 viel höher ist als die von Methode 2. Darüber hinaus testete der Editor auch eine große Tabelle mit 10 Millionen Elementen. Methode 1 überschritt das Speicherlimit, Methode 2 migrierte normal, benötigte aber mehr als 20 Minuten, und Methode 3 konnte immer noch innerhalb von 15 Minuten abgeschlossen werden. Damit ist dieser Artikel über die prinzipielle Analyse des MySQL-Extraktionsmodus für große Tabellen aus der Perspektive des Cloud-Datenmigrationsdienstes abgeschlossen. Weitere relevante Inhalte zur MySQL-Extraktion für große Tabellen finden Sie in früheren Artikeln auf 123WORDPRESS.COM oder in den folgenden verwandten Artikeln. Ich hoffe, Sie werden 123WORDPRESS.COM auch in Zukunft unterstützen! Das könnte Sie auch interessieren:
|
<<: Details zum JavaScript-Prototyp und zur Prototypkette
>>: W3C Tutorial (2): W3C Programme
1. Caches - Abfrage-Cache Die folgende Abbildung ...
Inhaltsverzeichnis Zyklusvergleich Verwendung Zus...
Einführung in Flex Layout Flex bedeutet auf Engli...
Szenario Angenommen, es gibt 10 Anfragen, aber di...
1. MySQL-Transaktionskonzept MySQL-Transaktionen ...
1. Installieren Sie Abhängigkeitspakete [root@loc...
Suchseite: search.wxml-Seite: <view class=&quo...
Inhaltsverzeichnis Frage Hintergrund Idee & U...
In diesem Artikelbeispiel wird der spezifische Co...
Vorwort In Bezug auf die Verwendung von MySQL-Ind...
Code kopieren Der Code lautet wie folgt: <HTML...
Indexerweiterung: InnoDB erweitert automatisch je...
Die Installation der Dekomprimierungsversion von ...
Das spezifische upgrade -Skript lautet wie folgt:...
SVG wurde in den letzten Jahren aufgrund seiner v...