Optimiser la requête de structure d'entité
Je suis en train de faire un stackoverflow clone de mon temps pour apprendre EF6 et MVC5, je suis actuellement à l'aide OWin pour l'authentification.
Tout fonctionne bien lorsque j'ai comme 50-60 questions, j'ai utilisé Porte rouge générateur de données et essayer de montée en puissance jusqu'à 1 million de questions avec un couple de milliers d'enfants lignes de la table sans relation juste pour le "stress" de l'ORM un peu. Voici comment le linq ressemble
var query = ctx.Questions
.AsNoTracking() //read-only performance boost.. http://visualstudiomagazine.com/articles/2010/06/24/five-tips-linq-to-sql.aspx
.Include("Attachments")
.Include("Location")
.Include("CreatedBy") //IdentityUser
.Include("Tags")
.Include("Upvotes")
.Include("Upvotes.CreatedBy")
.Include("Downvotes")
.Include("Downvotes.CreatedBy")
.AsQueryable();
if (string.IsNullOrEmpty(sort)) //default
{
query = query.OrderByDescending(x => x.CreatedDate);
}
else
{
sort = sort.ToLower();
if (sort == "latest")
{
query = query.OrderByDescending(x => x.CreatedDate);
}
else if (sort == "popular")
{
//most viewed
query = query.OrderByDescending(x => x.ViewCount);
}
}
var complaints = query.Skip(skipCount)
.Take(pageSize)
.ToList(); //makes an evaluation..
Inutile de dire que je suis SQL délais d'attente et après l'installation de Miniprofileret de regarder l'instruction sql générée, c'est une monstrueuse de quelques centaines de lignes de long.
Je sais que je suis de se joindre à/y compris trop de tables, mais comment de nombreux projets dans la vie réelle, nous n'avons qu'à joindre 1 ou 2 tables? Il pourrait y avoir des situations où nous devons le faire de nombreuses jointures avec des multi-millions de lignes, va procédures stockées le seul moyen?
Si c'est le cas, serait EF-être lui-même ne convient que pour les petits projets?
source d'informationauteur Lee Gary
Vous devez vous connecter pour publier un commentaire.
Plus probable que le problème que vous rencontrez est un Produit cartésien.
Fondées sur des données exemple:
Cette commande retourne le nombre de lignes vers le haut de
Sérieusement... c'est FOU le nombre de lignes à retourner.
Vraiment vous avez deux options si vous rencontrez ce problème:
D'abord: la voie de La facilité, de s'appuyer sur l'Entité Cadre de relier les modèles auto-magiquement comme ils entrent dans le contexte. Et ensuite, utiliser les entités
AsNoTracking()
et de disposer du contexte.Cela faire une demande par table, mais au lieu de 156 MILLIONS de lignes, vous ne téléchargez 110 lignes. Mais la partie la plus cool, c'est qu'ils sont tous installés dans le Contexte EF mémoire Cache, de sorte que maintenant le
questions
variable est remplie entièrement.Deuxième: Créer une procédure stockée qui retourne plusieurs tables et ont EF matérialiser les classes.
Je ne vois rien de toute évidence, le problème avec votre requête LINQ (
.AsQueryable()
ne devrait pas être obligatoire, mais ça ne change rien si vous l'enlever). Bien sûr, ne comprennent pas inutile de navigation propriétés (chacun ajoute un SQLJOIN
), mais si tout est nécessaire, il devrait être OK.Maintenant que le C# code à l'air bon, il est temps de voir le code SQL généré. Comme vous l'avez déjà fait, la première étape consiste à récupérer la requête SQL est exécutée. Il y a .Net façons de le fairepour SQL Server personnellement, je commence toujours un SQL Server session de profilage.
Une fois que vous avez la requête SQL, essayez de l'exécuter directement sur votre base de données, et n'oubliez pas d'inclure le le plan d'exécution réel. Cela va vous montrer exactement quelle partie de votre requête prend la majorité du temps. Il pourra même de vous indiquer si il y a évident manque index.
Maintenant, la question est de savoir si vous ajoutez tous ces indices de votre Serveur SQL server vous dit qu'ils sont manquantes? Pas nécessairement. Voir, par exemple,Ne vous contentez pas aveuglément à créer les index manquants. Vous aurez à choisir index qui doit être ajouté, qui ne devrait pas.
Comme un code-première approche créé des index pour vous, je suis en supposant que ceux sont des indices sur les clés primaires et étrangères. C'est un bon début, mais cela ne suffit pas. Je n'ai pas connu sur le nombre de lignes dans vos tables, mais un indice évident que vous pouvez uniquement ajouter des (pas d'outil de génération de code peut le faire parce qu'il est lié à votre entreprise de requêtes), est par exemple un index sur la
CreatedDate
colonne, comme vous êtes de la commande de vos articles par cette valeur. Si vous ne le faites pas, SQL Server vous devez exécuter une analyse de la table sur 1M de lignesqui sera évidemment désastreux en termes de performances.Donc :
Include
si vous pouvezComme vous le savez déjà, il y a la méthode générer monstrueux SQL.
Avertissement: je suis le propriétaire du projet Entity Framework Plus (EF+)
L'EF+ Requête IncludeOptimized méthode de permettre l'optimisation de SQL généré exactement comme EF Core faire.
Au lieu de générer un monstrueux SQL, SQL multiples est généré (un pour chaque include). Cette fonctionnalité est également comme un bonus permettent de filtrer les entités liées.
Docs: EF+ Requête IncludeOptimized
Prendre un coup d'oeil à la section 8.2.2 de ce document de Microsoft: