Pourquoi y a-t-il une sorte dans mon plan d'exécution?
J'ai la requête sql ci-dessous qui fonctionne très lentement. J'ai pris un coup d'oeil à l'exécution du plan et c'est de prétendre qu'un tri sur les Fichiers.N ° de commande est le coût le plus élevé de l'opération (53%). Pourquoi en serait-il passe si je ne suis pas de la commande par n ° de commande n'importe où? Est mon meilleur pari pour créer un index sur Fichier.N ° de commande?
Plan d'exécution si quelqu'un est intéressé.
with custOrders as
(
SELECT c.firstName + ' ' + c.lastname as Customer, c.PartnerId , c.CustomerId,o.OrderId,o.CreateDate, c.IsPrimary
FROM Customers c
LEFT JOIN CustomerRelationships as cr
ON c.CustomerId = cr.PrimaryCustomerId
INNER JOIN Orders as o
ON c.customerid = o.customerid
OR (cr.secondarycustomerid IS NOT NULL AND o.customerid = cr.secondarycustomerid)
where c.createdate >= @FromDate + ' 00:00'
AND c.createdate <= @ToDate + ' 23:59'
),
temp as
(
SELECT Row_number()
OVER (
ORDER BY c.createdate DESC) AS 'row_number',
c.customerid as customerId,
c.partnerid as partnerId,
c.Customer,
c.orderid as OrderId,
c.createdate as CreateDate,
Count(f.orderid) AS FileCount,
dbo.Getparentcustomerid(c.isprimary, c.customerid) AS ParentCustomerId,
au.firstname + ' ' + au.lastname AS Admin,
'' as blank,
0 as zero
FROM custOrders c
INNER JOIN files f
ON c.orderid = f.orderid
INNER JOIN admincustomers ac
ON c.customerid = ac.customerid
INNER JOIN adminusers au
ON ac.adminuserid = au.id
INNER JOIN filestatuses s
ON f.statusid = s.statusid
WHERE ac.adminuserid IS NOT NULL
AND f.statusid NOT IN ( 5, 6 )
GROUP BY c.customerid,
c.partnerid,
c.Customer,
c.isprimary,
c.orderid,
c.createdate,
au.firstname,
au.lastname
)
source d'informationauteur Abe Miessler
Vous devez vous connecter pour publier un commentaire.
SQL Server dispose de trois algorithmes de choisir à partir de quand il en a besoin pour joindre deux tables. Le sous-Boucles-joint, le Hash Join et le Tri-Fusion. Lequel il sélectionne elle se base sur des estimations de coûts. Dans ce cas, il a figuré, que sur la base des informations dont il disposait d'un Tri-Fusion-Joindre le bon choix.
Dans SQL Server plans d'exécution à une Sorte de Fusion est splitt en deux opérateurs, le Tri et la Fusion de la Rejoindre, car l'opération de tri pourrait ne pas être nécessaire, par exemple si les données sont triées déjà.
Pour plus d'informations sur les jointures découvrez ma jointure de la série ici: http://sqlity.net/en/1146/a-join-a-day-introduction/
L'article sur le Tri-Merg-Jointure est ici: http://sqlity.net/en/1480/a-join-a-day-the-sort-merge-join/
Afin de rendre votre requête plus vite, j'ai d'abord regarde index. Vous avez un tas d'index cluster scans dans la requête. Si vous pouvez remplacer quelques-uns d'entre eux avec vous cherche sera probablement mieux de. Vérifiez également que les estimations que SQL Server produit correspondant à la ligne de compte dans un plan d'exécution réel. S'ils sont loin, SQL Server fait souvent de mauvais choix. Afin de fournir de meilleures statistiques peuvent vous aider à la requête de la performance.
SQL Server effectue le tri pour permettre à la jointure de fusion entre le jeu de données pour le droit de l'opérateur de tri et les enregistrements dans la
Orders
table. Jointure de fusion lui-même est un moyen très efficace de rejoindre tous les enregistrements dans un jeu de données, mais il exige que chaque jeu de données pour être joint est triée en fonction de la jointure des touches et dans le même ordre.Depuis le
PK_Orders
clé est déjà commandé parOrderID
SQL Server a décidé de profiter de que par tri l'autre bout de la jointure (les autres trucs à droite de la sorte), de sorte que les deux ensembles de données peuvent être fusionnés à ce point dans le plan. La commune alternative à la fusion de jointure est une jointure de hachage, mais ce ne serait pas vous aider parce que vous seriez plutôt cher la jointure de hachage opérateur au lieu de les trier et de les fusionner. L'optimiseur de requête a déterminé les trier et de les fusionner pour être plus efficace dans ce cas.La cause racine de la pas cher dans le plan est la nécessité de combiner tous les enregistrements de la table commandes dans le dataset. Est-il un moyen de limiter le nombre d'enregistrements provenant de la
files
table? Un index surfiles.statusid
peut être utile si les documents ne sont pas en 5,6 sont à moins de 10% du total de la taille de la table.La QO pense que la plupart des enregistrements vont être filtrés à la fin. Essayez de pousser comme de nombreux de ces conditions de filtre de retour aux sources d'enregistrement de sorte que moins de dossiers à traiter dans le milieu du plan.
EDIT: j'ai oublié de mentionner, il est très utile d'avoir un plan d'exécution que l'on peut regarder. Est-il possible d'obtenir un réelle plan d'exécution de résultat pour voir le nombre réel d'enregistrements passant par ces opérateurs? Parfois, le estimé le nombre d'enregistrements peut être un peu hors.
EDIT: chercher à approfondir le 2ème et dernier opérateur de filtre du prédicat champ résumé:
Ressemble SQL Server est la production d'une jointure croisée entre toutes les correspondances possibles avec les enregistrements entre
Orders
etCustomers
jusqu'à ce point dans la requête (le plan sur la droite de la 2e à la dernière opérateur de filtre), puis de regarder chaque enregistrement de cette condition, pour voir si elle ne fait match. Remarquez comment la ligne qui va dans le filtre est vraiment gras et le trait qui est très mince? C'est parce que l'estimation du nombre de lignes va de 21k à 4 après que l'opérateur. Oubliez ce que j'ai dit plus tôt, c'est probablement le principal problème dans le plan. Même si il y a des indices sur ces colonnes, SQL Server ne peut pas utiliser, parce que la condition de jointure est trop complexe. Il est à l'origine du plan de fusion de tous les enregistrements au lieu de chercher à tout ceux dont vous avez besoin car il ne peut pas utiliser la pleine prédicat de jointure.Ma première pensée est de reformuler la CTE
custOrders
comme une union de deux ensembles de données: à l'aide d'CustomerId
et une à l'aide deSecondaryCustomerId
à la rejoindre. Ce sera dupliquer le travail du reste de la CTE, mais si elle permet la bonne utilisation de l'index, il pourrait être une grande victoire.Je pense que le tri est en cours pour cette jointure:
Je voudrais créer un index sur les fichiers qui contient les colonnes n ° de commande et statusid depuis la requête utilise également le statusid colonne.
Vous pouvez également envisager les modifications suivantes:
Je sais que cette question est assez vieux, cependant j'ai eu ce même problème et réalisé qu'il y avait un tout autre raison mes tables brutalement ralenti. Les symptômes étaient les mêmes, lent à la mise à jour des vues qui ont été précédemment la vitesse de l'éclair. "Trier" donner un coût de 40%.
Cette solution peut s'avérer utile à quelqu'un, et il est simple.
Lorsque la jointure de tables, assurez-vous de le rejoindre sur un "comparables".
J'ai été à joindre deux tables sur l'ID. Cependant, dans une table de ma carte d'identité a été défini comme un int et dans l'autre de type nvarchar. J'ai corrigé ce de les avoir tous les deux définis comme le même type et la vue est de retour à la vitesse de l'éclair.
j'espère que cela aidera quelqu'un d'autre afin d'éviter de passer une semaine à essayer de comprendre quel est le problème avec SQL, quand ils sont vraiment un PEBKAC moment.
(Problème Existe Entre Le Clavier Et La Chaise)