J'ai vu beaucoup de questions à ce sujet et les explications de Marc Gravell sur la raison pour laquelle il ne voulait pas continuer à jouer avec la grille multiple sur Dapper.
Mais je veux juste comprendre quelque chose
var grid = context.QueryMultiple(string.Join(" ; ", selectCommands));
return queries.Select(q => grid.Read<T>()).AsList();
Dans ce cas, QueryMultiple prend environ 3 secondes à exécuter (ce qui correspond à peu près au temps d’exécution sur le SQL) et la lecture de la grille comportant 2 requêtes prend 3 secondes au début, puis 9 secondes au second.
Il y a environ 50k lignes sur chacune et seulement 5 colonnes dont 2 int, 2 doubles (float sur sql) et une date / heure. J'ai essayé de désactiver la mise en mémoire tampon et cela n'a pas aidé.
Est-ce parce que Dapper commence par interroger la base de données uniquement pour que les requêtes soient exécutées? Puis se connecte à nouveau à la base de données sur demande pour la lecture et obtient toutes les données pour la lecture spécifique?
Serait-il préférable de créer quelques tâches asynchrones exécutées avec une requête unique?
J'ai vu beaucoup de questions à ce sujet et les explications de Marc Gravell sur la raison pour laquelle il ne veut pas continuer à jouer avec la grille multiple sur dapper
La raison la plus probable est, bien que nous exécutions la requête qui produit plusieurs résultats à l'aide de MARS - Multiple Active Result Sets
, mais vous ne pouvez toujours pas accéder à tous les ensembles de résultats en une fois. Ils peuvent être lus de manière séquentielle, car ils s'exécutent en interne à l'aide de la fonctionnalité NextResult
d'un DataReader
. Pour l’application, il reste toujours 1 appel, quand idéalement la même chose avec plusieurs appels Async ira toujours chercher tous les jeux de résultats en parallèle (utilisation idéale du système / des ressources).
Concernant votre requête:
queries.Select(q => grid.Read<T>()).AsList();
Je suppose que tous vos jeux de résultats sont du même type T
et que le résultat final que vous extrayez est du type List<IEnumerable<T>>
.
Maintenant, les options que vous avez est de modifier vos requêtes en utilisant Async-Await
comme suit:
var grid = await context.QueryMultipleAsync(string.Join(";",selectCommands));
return queries.Select(q => await grid.ReadAsync<T>()).AsList();
Est-ce que cela aiderait?
Dans une mesure limitée, en rendant les opérations asynchrones, mais les avantages seraient limités, car la lecture serait toujours séquentielle à l'aide de MARS.
Maintenant la partie principale de votre requête,
Dans ce cas, QueryMultiple prend environ 3 secondes à exécuter (ce qui correspond à peu près au temps d’exécution sur le SQL) et la lecture de la grille comportant 2 requêtes prend 3 secondes au début, puis 9 secondes au second.
Ceci est surprenant, Read est la seule opération effectuée ici, la requête a déjà été exécutée. Nous utilisons DataReader
, qui est déjà connecté par, ce qui est identique pour Dapper GridReader
, qui encapsule le DataReader
. Si seule la lecture prend tellement de temps que pour seulement 50 000 enregistrements, vous voudrez peut-être déterminer d'autres paramètres ayant un impact, tels que la vitesse du réseau, si la limite mémoire / RAM est atteinte, qui sont les facteurs externes ayant un impact considérable.
Est-ce parce que Dapper commence par interroger la base de données uniquement pour que les requêtes soient exécutées? Puis se connecte à nouveau à la base de données sur demande pour la lecture et obtient toutes les données pour la lecture spécifique?
Toujours une meilleure stratégie pour la raison suivante:
Cela dit, je suis toujours surpris que la lecture de 50 000 enregistrements soit si lente que ce soit des facteurs externes. Basculer les paramètres de la mémoire tampon n'aura pas d'incidence majeure sur les enregistrements de 50 Ko seulement, qu'ils sont bien compressés à l'aide de la sérialisation binaire. Normalement, la mémoire tampon est préférable, car son optimisation
La première chose que vous devez essayer est d'exécuter le même scénario de test sur du matériel relativement haut de gamme, plus de RAM, plus de processeur et un meilleur réseau d'E / S, juste pour comprendre si les modifications apportées au matériel apportent une amélioration, puisque Dapper est déjà optimisé même si vous utilisez QueryMultiple
et lu via GridReader