Comment améliorer les performances des requêtes

J'ai beaucoup d'loggings dans la table. Lorsque j'exécute la requête suivante, cela prend beaucoup de time. Comment puis-je améliorer la performance?

SET ROWCOUNT 10 SELECT StxnID ,Sprovider.description as SProvider ,txnID ,Request ,Raw ,Status ,txnBal ,Stxn.CreatedBy ,Stxn.CreatedOn ,Stxn.ModifiedBy ,Stxn.ModifiedOn ,Stxn.isDeleted FROM Stxn,Sprovider WHERE Stxn.SproviderID = SProvider.Sproviderid AND Stxn.SProviderid = ISNULL(@pSProviderID,Stxn.SProviderid) AND Stxn.status = ISNULL(@pStatus,Stxn.status) AND Stxn.CreatedOn BETWEEN ISNULL(@pStartDate,getdate()-1) and ISNULL(@pEndDate,getdate()) AND Stxn.CreatedBy = ISNULL(@pSellerId,Stxn.CreatedBy) ORDER BY StxnID DESC 

La table stxn a plus de 100 000 loggings.

La requête est exécutée à partir d'un visualiseur de rapport dans asp.net c #.

C'est mon article de reference quand j'essaie de faire une requête de search qui a plusieurs conditions de search qui peuvent être facultatives.

http://www.sommarskog.se/dyn-search-2008.html

Le plus gros problème avec votre requête est la column=ISNULL(@column, column) . MSSQL n'utilisera pas d'index pour cela. Pensez à le changer en (column = @column AND @column IS NOT NULL)

Vous devriez envisager d'utiliser le plan d'exécution et searchr les index manquants. Aussi, combien de time cela prend-il pour exécuter? Qu'est-ce qui est lent pour toi?

Peut-être que vous pourriez aussi ne pas returnner autant de lignes, mais c'est juste une supposition. En fait, nous devons voir votre table et vos index ainsi que le plan d'exécution.

Vérifiez sql-tuning-tutorial

Pour un, utilisez SELECT TOP () au lieu de SET ROWCOUNT – l'optimiseur aura une bien meilleure chance de cette façon. Une autre suggestion est d'utiliser une jointure interne correcte au lieu de finir avec un produit cartésien en utilisant l'ancienne table de style, la syntaxe de jointure de table (ce n'est pas le cas ici mais cela peut être beaucoup plus facile avec l'ancienne syntaxe). Devrait être:

 ... FROM Stxn INNER JOIN Sprovider ON Stxn.SproviderID = SProvider.Sproviderid ... 

Et si vous pensez que 100K lignes c'est beaucoup, ou que ce volume est une raison de lenteur, vous vous trompez lourdement. Très probablement, vous avez des stratégies d'indexing très mauvaises en place, peut-être des renifleurs de parameters, éventuellement des conversions implicites … difficile à dire sans comprendre les types de données, les index et le plan.

Il y a beaucoup de choses qui pourraient avoir un impact sur les performances de la requête. Bien que les loggings 100k ne soient pas vraiment nombreux.

Éléments à considérer (sans ordre particulier)

Matériel:

  1. La memory SQL Server est-elle contrainte? En d'autres termes, a-t-il assez de RAM pour faire son travail? Si la memory est échangée sur le disque, c'est un signe certain que vous avez besoin d'une mise à niveau.
  2. Le disque de la machine est-il contraint. En d'autres termes, les lecteurs sont-ils assez rapides pour répondre aux requêtes que vous devez exécuter? Si la memory est limitée, la vitesse du disque devient un facteur plus important.
  3. Le processeur de la machine est-il contraint? Par exemple, lorsque vous exécutez la requête, le processeur pointe-t-il pendant de longues périodes? Ou, y a-t-il déjà beaucoup d'autres requêtes en cours qui enlèvent des ressources des vôtres …

Structure de la database

  1. Avez-vous des index sur les colonnes utilisées dans votre clause where? Si les tables n'ont pas d'index, il faudra effectuer une parsing complète des deux tables pour déterminer quels loggings correspondent.
  2. Éliminer les appels de fonction ISNULL. S'il s'agit d'une requête directe, requestz au code appelant de valider les parameters et de définir les valeurs par défaut avant l'exécution. Si c'est dans une procédure stockée, faites les vérifications en haut du s'proc. Sauf si vous exécutez ceci avec RECOMPILE qui fait le reniflage des parameters, ces fonctions devront être évaluées pour chaque ligne.

Réseau:

  1. Le réseau est-il lent entre vous et le server? Selon la quantité de données extraites, vous pourriez tirer des Go de données à travers le fil. Je ne suis pas sûr de ce qui est stocké dans la colonne "brute". La première question que vous devez poser ici est "combien de données reviennent au client?" Par exemple, si chaque logging a une taille de plus de 1 Mo, vous aurez probablement des contraintes de disque et de réseau en jeu.

Général:

  1. Je ne suis pas sûr de ce que signifie «lent» dans votre question. Cela signifie-t-il que la requête prend environ 1 seconde à traiter ou cela signifie-t-il que cela prend 5 minutes? Tout est relatif ici.

Fondamentalement, il sera impossible de donner une réponse difficile sans beaucoup de questions posées par vous. Tous ces éléments seront corroborés si vous établissez le profil des requêtes, si vous comprenez quoi et combien revient au client et observez les interactions entre les différentes parties.

Enfin, en fonction de la quantité de données renvoyée au client, il se peut qu'il n'y ait pas moyen d'améliorer les performances, à l'exception des modifications matérielles.

Assurez-vous que Stxn.SproviderID, Stxn.status, Stxn.CreatedOn, Stxn.CreatedBy, Stxn.StxnID et SProvider.Sproviderid ont tous des index définis.

(NB – vous pourriez ne pas avoir besoin de tout, mais ça ne peut pas faire de mal.)

Je ne vois pas grand-chose qui peut être fait sur la requête elle-même, mais je peux voir que des choses sont faites sur le schéma:

  • Créer un index / PK sur Stxn.SproviderID
  • Créer un index / PK sur SProvider.Sproviderid
  • Créer des index sur le statut, CreatedOn, CreatedBy, StxnID

Quelque chose à considérer: Lorsque ROWCOUNT ou TOP sont utilisés avec une clause ORDER BY, l'set des résultats est créé et sortingé en premier, puis les 10 premiers résultats sont renvoyés.

Comment cela fonctionne-t-il sans la clause Order By?