Rumah  >  Artikel  >  pangkalan data  >  Menstrim kaedah pertanyaan dan pertanyaan kursor dalam MySQL (perkongsian ringkasan)

Menstrim kaedah pertanyaan dan pertanyaan kursor dalam MySQL (perkongsian ringkasan)

WBOY
WBOYke hadapan
2022-08-17 18:08:304099semak imbas

Artikel ini membawakan anda pengetahuan yang berkaitan tentang mysql Ia terutamanya memperkenalkan pertanyaan penstriman dan kaedah pertanyaan kursor dalam MySQL Ia mempunyai nilai rujukan yang baik dan saya harap ia akan membantu semua orang.

Menstrim kaedah pertanyaan dan pertanyaan kursor dalam MySQL (perkongsian ringkasan)

Pembelajaran yang disyorkan: tutorial video mysql

1 data daripada pangkalan data MySQL Baca 5 juta baris data untuk pemprosesan

Pindahkan data
  • Data eksport
  • Data proses kelompok
  • 2 . Senaraikan tiga kaedah pemprosesan A berikut

Pertanyaan biasa: baca 5 juta data ke dalam memori JVM pada satu masa, atau baca dalam halaman
  • Pertanyaan penstriman: baca satu bahagian pada satu masa dan muatkannya ke dalam memori JVM Pemprosesan perniagaan
  • Pertanyaan kursor: Seperti penstriman, bilangan keping data dibaca pada satu masa dikawal melalui parameter fetchSize
2.1 Pertanyaan umum

Secara lalai, set hasil carian lengkap disimpan dalam ingatan. Dalam kebanyakan kes, ini adalah cara yang paling cekap untuk beroperasi dan lebih mudah untuk dilaksanakan.

Dengan mengandaikan satu jadual mempunyai volum data sebanyak 5 juta, tiada siapa yang akan memuatkannya ke dalam memori sekali gus dan paging biasanya digunakan.

Di sini, demo ujian hanyalah untuk memantau JVM, jadi paging tidak digunakan dan data dimuatkan ke dalam memori pada satu masa

@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);
}
Pemantauan JVM

Kami akan mengurangkan saiz memori - melebihi had overhed GC

1 Kerap mencetuskan GC

Ada risiko OOM

2.2 Pertanyaan penstriman

Satu perkara yang perlu diambil perhatian tentang pertanyaan penstriman: semua baris dalam set hasil mesti dibaca (atau ditutup) sebelum sebarang pertanyaan lain boleh dikeluarkan pada sambungan, jika tidak pengecualian akan dilemparkan dan pertanyaan akan memonopoli sambungan.

Daripada keputusan ujian, pertanyaan penstriman tidak meningkatkan kelajuan pertanyaan

Pemantauan JVM

Kami akan mengurangkan memori timbunan -Xms70m -Xmx70m

@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);
}
Kami mendapati bahawa walaupun ingatan timbunan hanya 70m, OOM masih tidak berlaku

2.3 Pertanyaan kursor

Nota :

1. Parameter perlu disambungkan ke dalam maklumat sambungan pangkalan data useCursorFetch=true

2 , seperti 1000 pada satu masa

Berdasarkan keputusan ujian, pertanyaan kursor telah memendekkan kelajuan pertanyaan pada tahap tertentu

Pemantauan JVM

Kami akan timbunan Kurangkan saiz memori -

@Test
public void cursorQuery() throws Exception {
    Class.forName("com.mysql.jdbc.Driver");
    // 注意这里需要拼接参数,否则就是普通查询
    conn = DriverManager.getConnection("jdbc:mysql://101.34.50.82:3306/mysql-demo?useCursorFetch=true", "root", "123456");
    start = System.currentTimeMillis();
 
     // 1核2G:查询一百条记录:52 ms
     // 1核2G:查询一千条记录:1095 ms
    // 1核2G:查询一万条记录:17432 ms
    // 1核2G:查询五万条记录:90244 ms
    String sql = "select * from wh_b_inventory limit 50000";
    ((JDBC4Connection) conn).setUseCursorFetch(true);
    statement = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
    statement.setFetchSize(1000);
    ResultSet rs = statement.executeQuery(sql);
    int count = 0;
    while (rs.next()) {
        count++;
    }
    System.out.println(count);
}

3. RowData

Logik ResultSet.next() adalah untuk melaksanakan kelas ResultSetImpl dan dapatkannya daripada RowData setiap kali Data untuk baris seterusnya. RowData ialah antara muka dan rajah perhubungan pelaksanaan adalah seperti berikut


3.1 RowDataStatic

Secara lalai, ResultSet akan menggunakan contoh RowDataStatic dan ResultSet akan digunakan apabila menjana objek RowDataStatic Baca semua rekod dalam memori ke dalam memori, dan kemudian baca satu persatu daripada memori hingga seterusnya()

3.2 RowDataDynamic

Apabila pemprosesan penstriman digunakan, ResultSet menggunakan objek RowDataDynamic, dan Setiap panggilan ke objek next() ini akan memulakan IO untuk membaca satu baris data

3.3 RowDataCursor

Panggilan ke RowDataCursor adalah pemprosesan kelompok, dan kemudian dicache secara dalaman. Prosesnya adalah seperti berikut:

Pertama, ia akan menyemak sama ada terdapat data dalam penimbal dalamannya yang belum dikembalikan, ia akan mengembalikan baris seterusnya

Jika semua bacaan selesai, cetuskan permintaan baharu kepada Pelayan MySQL untuk membaca hasil kuantiti fetchSize

Dan penimbal hasil pulangan ke penimbal dalaman, dan kemudian kembalikan baris pertama data

    Ringkasnya:
  • RowDataStatic lalai membaca semua Data dipindahkan ke memori klien, iaitu JVM kami
  • RowDataDynamic membaca satu keping data setiap panggilan IO;
RowDataCursor membaca baris fetchSize pada satu masa, dan kemudian memulakan panggilan permintaan selepas penggunaan selesai.

4. Prinsip komunikasi JDBC

Interaksi antara JDBC dan pelayan MySQL diselesaikan melalui Socket Sesuai dengan pengaturcaraan rangkaian, MySQL boleh dianggap sebagai SocketServer, jadi pautan permintaan yang lengkap :

Pelanggan JDBC-> Soket Pelanggan -> >4.1 generalQuery Pertanyaan umum

Pertanyaan umum akan memuatkan semua data yang ditanya ke dalam JVM dan kemudian memprosesnya.

Jika jumlah data pertanyaan terlalu besar, ia akan terus mengalami GC, dan kemudian akan berlaku limpahan memori

4.2 pertanyaan penstriman streamQuery

Pelayan sedang sedia untuk kembali daripada sekeping data pertama Apabila data dimuatkan ke dalam penimbal, data dimuatkan ke dalam penimbal kernel mesin klien melalui pautan TCP Kaedah inputStream.read() JDBC akan dibangkitkan untuk membaca Satu-satunya perbezaan ialah aliran dihidupkan Apabila membaca, hanya satu saiz pakej data dibaca dari kernel setiap kali, dan hanya satu baris data dikembalikan Jika satu pakej tidak dapat mengumpulkan satu baris data pakej akan dibaca.

4.3 cursorQuery Cursor Query

Apabila kursor dihidupkan, apabila pelayan mengembalikan data, ia akan mengembalikan data mengikut saiz fetchSize, dan pelanggan akan mengembalikan data setiap kali apabila menerima data. Tukar data penimbal dan baca semua data Jika data mempunyai 100 juta data, jika FetchSize ditetapkan kepada 1000, 100,000 komunikasi pergi balik akan dilakukan apabila pelanggan telah selesai menggunakan data , dan jadual sepadannya sendiri mungkin mempunyai operasi tulis DML Pada masa ini, MySQL perlu mencipta ruang sementara untuk menyimpan data yang perlu diambil.

Jadi apabila anda mendayakan useCursorFetch untuk membaca jadual besar, anda akan melihat beberapa fenomena pada MySQL:

1 IOPS melonjak

2
  • 3 Selepas klien JDBC memulakan SQL, ia menunggu lama untuk data respons SQL Pada masa ini, pelayan sedang menyediakan data
  • 4 , penghantaran data bermula peringkat, tindak balas rangkaian mula melonjak, dan IOPS berubah daripada "baca dan tulis" kepada "baca".
  • IOPS (Input/Output Per Second): Bilangan cakera membaca dan menulis sesaat
  • 5 CPU dan memori akan meningkat dengan peratusan tertentu
  • 5. Senario serentak
  • Panggilan serentak: Jmete 10 utas panggilan serentak dalam 1 saat

Laporan prestasi memori pertanyaan penstriman adalah seperti berikut

Panggilan serentak juga OK untuk penggunaan memori, tidak wujud Peningkatan bertindan

Laporan prestasi memori pertanyaan kursor adalah seperti berikut

6. Ringkasan

1. Kedua-dua pertanyaan kursor dan pertanyaan penstriman boleh mengelakkan OOM dalam satu urutan; pertanyaan. Masa;

3. Dalam senario serentak, aliran memori timbunan pertanyaan penstriman adalah lebih stabil, dan tiada peningkatan tambahan.

Pembelajaran yang disyorkan:

tutorial video mysql

Atas ialah kandungan terperinci Menstrim kaedah pertanyaan dan pertanyaan kursor dalam MySQL (perkongsian ringkasan). Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:jb51.net. Jika ada pelanggaran, sila hubungi admin@php.cn Padam