Dieser Artikel vermittelt Ihnen relevantes Wissen über MySQL. Er stellt hauptsächlich die Streaming-Abfrage- und Cursor-Abfragemethoden in MySQL vor. Er hat einen guten Referenzwert und ich hoffe, dass er für alle hilfreich ist.
Empfohlenes Lernen: MySQL-Video-Tutorial
Jetzt muss das Geschäftssystem 5 Millionen Datenzeilen aus der MySQL-Datenbank zur Verarbeitung lesen
Standardmäßig wird der vollständige Abrufergebnissatz gespeichert Erinnerung. In den meisten Fällen ist dies die effizienteste Vorgehensweise und einfacher umzusetzen.
Angenommen, eine einzelne Tabelle hat ein Datenvolumen von 5 Millionen, niemand wird sie sofort in den Speicher laden und im Allgemeinen wird Paging verwendet.
Hier dient die Testdemo nur der Überwachung der JVM, daher wird kein Paging verwendet und die Daten werden auf einmal in den Speicher geladen
Der gesamte Abfrageprozess erhöht die Heap-Speichernutzung allmählich und führt schließlich zu OOM:java.lang.OutOfMemoryError: GC-Overhead-Limit überschritten
1. GC wird häufig ausgelöst2 Es gibt versteckte OOM-Gefahren
2.2 Streaming-Abfrage
Eine Sache, die Sie bei Streaming-Abfragen beachten sollten: Alle Zeilen im Ergebnissatz müssen gelesen (oder geschlossen) werden, bevor andere Abfragen für die Verbindung ausgegeben werden können, andernfalls wird eine Ausnahme ausgelöst und die entsprechende Abfrage ausgelöst wird die Verbindung monopolisieren.
Den Testergebnissen nach zu urteilen, hat die Streaming-Abfrage die Abfragegeschwindigkeit nicht verbessert
@Test public void generalQuery() throws Exception { // 1核2G:查询一百条记录:47ms // 1核2G:查询一千条记录:2050 ms // 1核2G:查询一万条记录:26589 ms // 1核2G:查询五万条记录:135966 ms String sql = "select * from wh_b_inventory limit 10000"; ps = conn.prepareStatement(sql); ResultSet rs = ps.executeQuery(sql); int count = 0; while (rs.next()) { count++; } System.out.println(count); }
2.3 Cursorabfrage
Hinweis:
1. Parameter müssen in den Datenbankverbindungsinformationen gespleißt werden
useCursorFetch=true2. Zweitens legen Sie die Anzahl der von der Anweisung gelesenen Daten fest B. 1000 auf einmal@Test public void streamQuery() throws Exception { // 1核2G:查询一百条记录:138ms // 1核2G:查询一千条记录:2304 ms // 1核2G:查询一万条记录:26536 ms // 1核2G:查询五万条记录:135931 ms String sql = "select * from wh_b_inventory limit 50000"; statement = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); statement.setFetchSize(Integer.MIN_VALUE); ResultSet rs = statement.executeQuery(sql); int count = 0; while (rs.next()) { count++; } System.out.println(count); }
JVM-Überwachung
Wir haben den Heapspeicher reduziert -Xms70m -Xmx70m
Das haben wir festgestellt In einem Single-Thread-Fall können Cursorabfragen wie Streaming-Abfragen sehr gut vermieden werden, OOM zu vermeiden, und Cursorabfragen können die Abfragegeschwindigkeit optimieren.
3. RowData
ResultSet.next() Die Logik besteht darin, die Klasse ResultSetImpl zu implementieren, um jedes Mal die nächste Datenzeile von RowData abzurufen. RowData ist eine Schnittstelle und das Implementierungsbeziehungsdiagramm lautet wie folgt: 3.1 RowDataStatic: Standardmäßig verwendet ResultSet die RowDataStatic-Instanz. Wenn das RowDataStatic-Objekt generiert wird, werden alle Datensätze im ResultSet in den Speicher eingelesen. und dann durch next() geleitet. Eins nach dem anderen aus dem Speicher lesen
3.2 RowDataDynamic
Wenn Streaming-Verarbeitung verwendet wird, verwendet ResultSet das RowDataDynamic-Objekt, und dieses Objekt initiiert IO, um jedes Mal, wenn next() ist, eine einzelne Datenzeile zu lesen aufgerufen
3.3 RowDataCursor
Wenn der gesamte Lesevorgang abgeschlossen ist, wird eine neue Anforderung zum Lesen des fetchSize-Mengenergebnisses ausgelöst
JDBC-Client –> Client-Socket –> MySQL-Kernel-Socket-Puffer –> Eine gewöhnliche Abfrage lädt alle abgefragten Daten in die JVM und verarbeitet sie dann.
Wenn die Menge der Abfragedaten zu groß ist, kommt es weiterhin zu GC und dann kommt es zu einem Speicherüberlauf4.2 streamQuery-Streaming-AbfrageWenn der Server bereit ist, von den ersten Daten zurückzukehren, wird er geladen Die Daten werden in den Puffer übertragen und die TCP-Verbindung wird in den Kernel-Puffer des Client-Computers eingefügt. Die Methode inputStream.read() von JDBC wird aktiviert, um die Daten zu lesen Wenn es aktiviert ist, liest es jedes Mal nur Daten einer Paketgröße und gibt nur eine Datenzeile zurück. Wenn ein Paket eine Datenzeile nicht zusammenstellen kann, wird ein anderes Paket gelesen. 4.3 CursorQuery Cursor-AbfrageWenn der Cursor aktiviert ist und der Server Daten zurückgibt, gibt er Daten entsprechend der Größe von fetchSize zurück, und wenn der Client Daten empfängt, liest er jedes Mal alle Pufferdaten. Wenn die Daten 100 Millionen Daten umfassen und FetchSize auf 1000 eingestellt ist, werden 100.000 Roundtrip-Kommunikationen durchgeführt. Da MySQL nicht weiß, wann der Client die Daten verbraucht hat, verfügt seine eigene entsprechende Tabelle möglicherweise über eine DML-Schreiboperation. Zu diesem Zeitpunkt muss MySQL einen temporären Speicherplatz erstellen, um die Daten zu speichern, die entfernt werden müssen. Wenn Sie also useCursorFetch zum Lesen einer großen Tabelle aktivieren, werden Sie bei MySQL mehrere Phänomene beobachten:1. IOPS steigt
2. Speicherplatz steigt
6. Zusammenfassung
1. Sowohl die Cursorabfrage als auch die Streaming-Abfrage können OOM in einem einzelnen Thread vermeiden.
2 mit gewöhnlicher Abfrage;
3. In gleichzeitigen Szenarien ist der Trend des Streaming-Abfrage-Heapspeichers stabiler und es gibt keinen additiven Anstieg.
Empfohlenes Lernen:MySQL-Video-Tutorial
Das obige ist der detaillierte Inhalt vonStreaming-Abfrage- und Cursor-Abfragemethoden in MySQL (Zusammenfassungsfreigabe). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!