0

J'ai cette requête de jointure interne simple et sa table maître de plan d'exécution a environ 34K enregistrements et la table de détail a environ 51K enregistrements. Mais cette simple requête suggère d'ajouter un index avec include (contenant toutes les colonnes maîtresses que j'ai incluses dans le select). Je ne m'attendais pas à ce que ce soit la raison et le remède.Jointure interne simple suggérant un index Include

DECLARE  
     @StartDrInvDate Date ='2017-06-01', 
     @EndDrInvDate Date='2017-08-31' 

    SELECT 
     Mastertbl.DrInvoiceID, 
     Mastertbl.DrInvoiceNo, 
     Mastertbl.DistributorInvNo, 
     PreparedBy, 
     detailtbl.BatchNo, detailtbl.Discount, 
     detailtbl.TradePrice, detailtbl.IssuedUnits, 
     detailtbl.FreeUnits 
    FROM 
     scmDrInvoices Mastertbl 
    INNER JOIN 
     scmDrInvoiceDetails detailtbl ON Mastertbl.DrInvoiceID = detailtbl.DrInvoiceID 
    WHERE 
     (Mastertbl.DrInvDate BETWEEN @StartDrInvDate AND @EndDrInvDate) 

enter image description here

Ma vraie curiosité est pourquoi il suggère cet indice - je vois normalement pas ce comportement avec les grandes tables

+0

Avec ce nombre de lignes vous pouvez ignorer la suggestion à condition que vous soyez satisfait de la performance actuelle. – Serg

+0

Juste parce que SQL Server a demandé cela ne signifie pas que vous devriez créer cela. Il base ses hypothèses sur le plan d'exécution qu'il a utilisé sur cette requête particulière. Essayez d'ajouter un index non cluster sur Mastertbl.DrInvoiceID et incluez Mastertbl.DrInvDate. Regardez la requête et jouez sur les index. :) – dbajtr

+0

@Serg Cette requête fait en fait partie d'une requête plus longue qui prenait du temps et cette requête suggérait cet index quand j'enlèverais toutes les autres jointures et je n'ai que ceci à gauche et suggérant toujours le même index – Zia

Répondre

1

Pour cette requête:

SELECT m.DrInvoiceID, m.DrInvoiceNo, m.DistributorInvNo, 
     PreparedBy, 
     d.BatchNo, d.Discount, d.TradePrice, d.IssuedUnits, d.FreeUnits 
FROM scmDrInvoices m INNER JOIN 
    scmDrInvoiceDetails d 
    ON m.DrInvoiceID = d.DrInvoiceID 
WHERE m.DrInvDate BETWEEN @StartDrInvDate AND @EndDrInvDate; 

Je me attends les indices de base doivent être: scmDrInvoices(DrInvDate, DrInvoiceID) et scmDrInvoiceDetails(DrInvoiceID). Cet index permettrait au moteur de recherche d'identifier rapidement les lignes correspondant au WHERE dans la table principale, puis de rechercher les valeurs correspondantes dans scmDrInvoiceDetails.

Le reste des colonnes pourrait alors être inclus dans l'un ou l'autre des index, de sorte que les index couvriraient la requête. "Couverture" signifie que toutes les colonnes sont dans l'index, de sorte que le plan de requête n'a pas besoin de se référer aux pages de données d'origine.

La stratégie ci-dessus est ce que SQL Server suggère.

+0

Oui ces indexés sont déjà là – Zia

1

Vous pouvez peut-être voir la logique de pourquoi il suggère d'indexer la date de facturation; il a fait un certain calcul sur le nombre de lignes que vous voulez en dehors du nombre de lignes qu'il pense actuellement, et il semble que la sélectivité d'un index sur cette colonne mérite d'être indexée. Si vous voulez 3 lignes sur 55 000, et vous le voulez toutes les 5 minutes pour toujours, il est logique d'indexer. Surtout si le taux de croissance de ce tableau signifie que l'année prochaine ce sera 3 rangs sur 5,5 millions. La recommandation include recommande peut-être plus naïvement d'associer suffisamment de données supplémentaires aux valeurs indexées pour que l'intégralité de l'ensemble de données demandé par la table principale puisse être résolue à partir de l'index, sans toucher la table - les index sont essentiellement des pointeurs vers une ligne table; Lorsque le moteur de recherche a utilisé l'index pour localiser toutes les lignes dont il aura besoin, il lui faut ensuite balayer la table pour obtenir les données souhaitées. En incluant des données dans un index, vous supprimez le besoin d'aller à la table et parfois, mais pas d'autres (créer plusieurs index qui reproduisent la plupart/toutes les données d'une table pour des requêtes rarement exécutées est une perte d'espace disque). En outre, la fréquence à laquelle vous exécutez cette requête dans un outil de débogage affecte l'opinion de SQLServer sur la fréquence d'utilisation de la requête. Je trouve régulièrement mon portail SQLAzure en faisant des recommandations d'index grâce aux devs qui exécutent une requête encore et encore, en la déboguant, quand je sais que dans prod, cette requête sera utilisée une fois par mois, donc je rejette la recommandation de créer un index Ces recommandations ne doivent donc pas être prises en compte aveuglément car SQLServer ne sait pas ce que vous avez l'intention d'utiliser, ou des requêtes similaires pour dans les applications du monde réel.La création et la maintenance de l'index doivent être effectuées avec soin et attention; par exemple, il se peut que cette requête demande cet index, une autre requête souhaiterait un index sur une colonne différente, mais il peut être judicieux de créer un index qui clavette sur les deux colonnes (dans un ordre particulier), puis dans toutes les requêtes. Sur la colonne indexée en second lieu, incluez un prédicat qui frappe la première colonne indexée, que la requête en ait besoin

Exemple: dans votre tableau de factures, vous avez une colonne indiquant si elle est payée ou non, et ailleurs dans votre application vous avez une autre requête qui compte le nombre de factures impayées. Vous pouvez avoir 2 index - un sur la date de facture (pour cette requête) et un sur le statut (pour cette requête) ou sur les deux colonnes (statut, date) et dans cette requête ont des prédicats de WHERE status = 'unpaid' AND date between... même si le prédicat de statut est redondant . Pourquoi pourrait-il être redondant? Supposons que vous ne choisissiez que des factures de la semaine dernière qui n'ont pas encore été envoyées, donc ne peuvent jamais être payées. C'est ce que je veux dire par "soyez réfléchi à l'indexation" - vous en savez beaucoup sur votre application. SQLServer ne peut jamais comprendre ... En incluant la colonne d'état redondant dans la requête "get invoices from the week week" (même si l'état est logiquement redondant), vous autorisez le moteur de requête à utiliser un index commandé par statut, puis par date . Cela signifie que vous pouvez vous contenter d'avoir à seulement maintenir un index, et il peut être utilisé par deux requêtes

de maintenance des index et la logique de la création peut être un emploi à temps plein ..;)