Maison > Article > base de données > Méthodes de requête en streaming et de requête de curseur dans MySQL (partage de résumé)
Cet article vous apporte des connaissances pertinentes sur mysql Il présente principalement les méthodes de requête en streaming et de requête par curseur dans MySQL. Il a une bonne valeur de référence et j'espère qu'il sera utile à tout le monde.
Apprentissage recommandé : Tutoriel vidéo MySQL
Maintenant, le système d'entreprise doit lire 5 millions de lignes de données de la base de données MySQL pour le traitement
Par défaut, l'ensemble complet des résultats de récupération sera stocké en mémoire . Dans la plupart des cas, il s’agit de la manière la plus efficace de fonctionner et la plus facile à mettre en œuvre.
En supposant qu'une seule table ait un volume de données de 5 millions, personne ne la chargera dans la mémoire en même temps et la pagination est généralement utilisée.
Ici, la démo de test sert uniquement à surveiller la JVM, donc la pagination n'est pas utilisée et les données sont chargées dans la mémoire en même temps
@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); }
Surveillance JVM
Nous ajusterons la mémoire à -Xms70m -Xmx70m
tout le processus de requête, l'utilisation de la mémoire du tas augmente progressivement et conduit finalement à un MOO :
java.lang.OutOfMemoryError : limite de surcharge du GC dépassée
1 Déclenchement fréquent du GC
2.
2.2 Requête en streaming Une chose à noter à propos des requêtes en streaming : toutes les lignes du jeu de résultats doivent être lues (ou fermées) avant que toute autre requête puisse être émise sur la connexion, sinon une exception sera levée et la requête monopolisera la connexion. À en juger par les résultats des tests, la requête en streaming n'a pas amélioré la vitesse de requête@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); }
Surveillance JVM
Nous avons réduit la mémoire du tas -Xms70m -Xmx70mNous avons constaté que même si la mémoire du tas n'était que de 70 m, elle restait ne s'est pas produit MOO 2.3 Requête du curseurRemarque : 1. Besoin de fusionner les paramètres dans les informations de connexion à la base de donnéesuseCursorFetch=true
2. Deuxièmement, définissez le nombre de données lues par Statement à chaque fois. , comme en lire 1 000 à la foisÀ en juger par les résultats des tests, la requête du curseur a réduit la vitesse de requête dans une certaine mesure
@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);
}
Nous avons réduit la mémoire du tas -Xms70m -Xmx70m
Nous avons trouvé que dans un cas monothread, les requêtes de curseur Comme les requêtes de streaming, le MOO peut être très bien évité et les requêtes de curseur peuvent optimiser la vitesse des requêtes.
3. RowData
3.1 RowDataStatic
3.2 RowDataDynamic
3.3 RowDataCursor
Le RowDataStatic par défaut lit toutes les données dans la mémoire du client, il s'agit également de notre JVM ;
RowDataDynamic lit une donnée par appel IO
RowDataCursor lit les lignes fetchSize à la fois, puis lance un appel de demande une fois la consommation terminée.
4.Principe de communication JDBC
Client JDBC -> Client Socket -> MySQL -> Récupérer les données renvoyées -> MySQL Kernel Socket Buffer -> Client Socket Buffer -> Une requête ordinaire chargera toutes les données interrogées dans la JVM, puis les traitera.
Si la quantité de données de requête est trop importante, elle continuera à subir GC, puis il y aura un débordement de mémoire4.2 Requête de streaming streamQueryLorsque le serveur est prêt à revenir des premières données, il se chargera les données dans le tampon, et les données passeront par la liaison TCP, dans le tampon du noyau de la machine client, la méthode inputStream.read() de JDBC sera réveillée pour lire les données. La seule différence est que lorsque la lecture du flux est activée, elle est activée. lit uniquement à partir du noyau à chaque fois. Prendre des données d'une taille de package ne renvoie qu'une seule ligne de données. Si un package ne peut pas assembler une ligne de données, un autre package sera lu. 4.3 CursorQuery Cursor QueryLorsque le curseur est activé, lorsque le serveur renvoie des données, il renverra des données en fonction de la taille de fetchSize, et lorsque le client recevra des données, il lira toutes les données du tampon à chaque fois. si les données contiennent 100 millions de données, si FetchSize est défini sur 1 000, 100 000 communications aller-retour seront effectuées Puisque MySQL ne sait pas quand le client a fini de consommer les données, sa propre table correspondante peut avoir une opération écrite DML ; à ce stade, MySQL doit créer un espace temporaire pour stocker les données qui doivent être supprimées. Ainsi, lorsque vous activez useCursorFetch pour lire une grande table, vous verrez plusieurs phénomènes sur MySQL :1 L'IOPS monte en flèche
2. L'espace disque monte en flèche
Le rapport sur les performances de la mémoire de la requête de curseur est le suivant
6. Résumé
1. La requête de curseur et la requête de streaming peuvent éviter le MOO dans un seul thread
2. La requête de curseur est plus rapide que la requête de streaming en termes de vitesse de requête, et la requête de streaming ne peut pas raccourcir le temps de requête par rapport. avec une requête ordinaire ; 3. Dans des scénarios simultanés, la tendance de la mémoire du segment de requête en streaming est plus stable et il n'y a pas d'augmentation additive. Apprentissage recommandé :Tutoriel vidéo mysql
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!