L'entité code de la structure est lente lors de l'utilisation de l'Inclure() plusieurs fois
J'ai été le débogage d'une certaine lenteur code et il semble que le coupable est l'EF code affiché ci-dessous. Il faut 4-5 secondes lorsque la requête est évaluée à un stade ultérieur. Je suis en train de le faire fonctionner en moins de 1 seconde.
J'ai testé ce à l'aide de SQL Server Profiler, et il semble qu'un tas de scripts SQL sont exécutées. Il confirme également qu'il faut 3 à 4 secondes avant de SQL server est fait avec les exécutions.
J'ai lu d'autres questions similaires à propos de l'utilisation de include() et il ne semble pas qu'il y est une baisse des performances lorsque vous l'utilisez. J'ai essayé de diviser le code ci-dessous dans plusieurs requêtes différentes, mais il ne fait pas beaucoup de différence.
Une idée de comment je peux obtenir le ci-dessous pour une exécution plus rapide?
Actuellement l'application web, je travaille sur est de montrer le vide de l'iframe en attendant le ci-dessous pour compléter. Si je ne peux pas obtenir une exécution plus rapide de temps que j'ai à les diviser et partiellement à la charge de l'iframe avec des données ou aller avec une autre solution asynchrone. Toutes les idées ici serait également appréciée!
using (var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions { IsolationLevel = System.Transactions.IsolationLevel.ReadUncommitted }))
{
formInstance = context.FormInstanceSet
.Includes(x => x.Include(fi => fi.FormDefinition).Include(fd => fd.FormSectionDefinitions).Include(fs => fs.FormStateDefinitionEditableSections))
.Includes(x => x.Include(fi => fi.FormDefinition).Include(fd => fd.FormStateDefinitions))
.Includes(x => x.Include(fi => fi.FormSectionInstances).Include(fs => fs.FormFieldInstances).Include(ff => ff.FormFieldDefinition).Include(ffd => ffd.FormFieldMetaDataDefinition).Include(ffmdd => ffmdd.ComplexTypePropertyNames))
.Include(x => x.CurrentFormStateInstance)
.Include(x => x.Files)
.FirstOrDefault(x => x.FormInstanceIdentifier == formInstanceIdentifier);
scope.Complete();
}
- Qu'est-ce que Comprend(avec un "s")? C'est une extension propriétaire?
- Je crois que c'était une méthode d'extension de la chaîne d'inclure, notamment si cela a du sens. Je n'ai pas accès au code plus donc je ne peux pas vous dire exactement ce que c'était mais c'est ma meilleure supposition de ce que je me souviens.
Vous devez vous connecter pour publier un commentaire.
Que c'est un euphémisme! Plusieurs
Include
s rapidement exploser le résultat de la requête SQL à la fois en largeur et en longueur. Pourquoi est-ce?tl;dr Plusieurs
Include
s exploser le SQL jeu de résultats. Bientôt, il devient moins cher pour charger des données par de multiples appels de base de données au lieu de courir un mega déclaration. Essayer de trouver le meilleur mélange deInclude
etLoad
consolidés.Facteur de croissance de
Include
sDisons que nous avons
Root
Root.Parent
Root.Children1
etRoot.Children2
Root.Include("Parent").Include("Children1").Include("Children2")
Cela construit une instruction SQL qui a la structure suivante:
Ces
<PseudoColumns>
consistent en des expressions commeCAST(NULL AS int) AS [C2],
et ils servent à avoir le même nombre de colonnes dans tous lesUNION
-ed requêtes. La première partie ajoute pseudo colonnes pourChild2
, la deuxième partie ajoute pseudo colonnes pourChild1
.C'est ce que cela signifie pour la taille de la SQL jeu de résultats:
SELECT
clause est la somme de toutes les colonnes dans les quatre tablesPuisque le nombre total de points de données est
columns * rows
, chaqueInclude
augmente de façon exponentielle le nombre total de points de données dans le jeu de résultats. Permettez-moi de démontrer que la prise deRoot
à nouveau, maintenant avec un supplément deChildren3
collection. Si toutes les tables ont 5 colonnes et 100 lignes, on obtient:Un
Include
(Root
+ 1 enfant de la collection): 10 colonnes * 100 lignes = 1000 points de données.Deux
Include
s (Root
+ 2 enfants de collections): 15 colonnes * 200 lignes = 3000 points de données.Trois
Include
s (Root
+ 3 enfants de collections): 20 colonnes * 300 lignes = 6000 points de données.Avec 12
Includes
cela reviendrait à 78000 points de données!À l'inverse, si vous obtenez tous les enregistrements de chaque table séparément au lieu de 12
Includes
, vous avez13 * 5 * 100
points de données: 6500, moins de 10%!Maintenant ces chiffres sont quelque peu exagérées en ce que de nombreux de ces points de données seront
null
, de sorte qu'ils ne contribuent pas beaucoup à la taille réelle de l'ensemble de résultats est envoyé au client. Mais la requête de la taille et de la tâche pour l'optimiseur de requête certainement affectée négativement par l'augmentation du nombre deInclude
s.Équilibre
Donc à l'aide d'
Includes
est un délicat équilibre entre le coût des appels de base de données et le volume des données. Il est difficile de donner une règle du pouce, mais maintenant vous pouvez imaginer que le volume de données généralement rapidement devient plus grand que le coût des appels supplémentaires si il y a plus de ~3Includes
pour enfant collections (mais un peu plus pour les parentsIncludes
, que seulement d'élargir le jeu de résultats).Alternative
L'alternative à
Include
est pour charger des données dans les requêtes distinctes:Cette charge toutes les données requises dans le cadre de la cache. Au cours de ce processus, EF s'exécute relation de correction par lequel il s'est auto-remplit les propriétés de navigation (
Root.Children
etc.) chargé d'entités. Le résultat final est identique à la déclaration deInclude
s, sauf pour une différence importante: l'enfant collections ne sont pas marqués comme chargé dans l'état de l'entité gestionnaire, de manière EF va essayer de déclencher le chargement paresseux si vous y avez accès. C'est pourquoi il est important de désactiver le chargement paresseux.En réalité, vous aurez à déterminer quelle combinaison de
Include
etLoad
états qui fonctionnent le mieux pour vous.Vous avez correctement configuré les relations entre toutes les entités que vous essayez de "inclure"? Si au moins une entité ne dispose pas d'une relation à d'autres entités, puis EF sera pas en mesure de construire une requête complexe à l'aide de SQL syntaxe de jointure - à la place, il va exécuter autant de requêtes que de nombreux "comprend" que vous avez. Et bien sûr, qui va conduire à des problèmes de performances. Pourriez-vous s'il vous plaît poster exactement requête(-es) généré par EF afin d'obtenir les données?