Question

J'ai des procédures stockées complexes qui peuvent renvoyer plusieurs milliers de lignes et dont le traitement prend beaucoup de temps.

Existe-t-il un moyen de savoir combien de lignes vont être renvoyées avant que la requête ne soit exécutée et récupère les données?

C’est avec Visual Studio 2005, une application Winforms et SQL Server 2005.

Était-ce utile?

La solution

Une solution à votre problème pourrait être de réécrire la procédure stockée afin qu'elle limite l'ensemble de résultats à un certain nombre, comme:

SELECT TOP 1000 * FROM tblWHATEVER

dans SQL Server ou

SELECT * FROM tblWHATEVER WHERE ROWNUM <= 1000

dans Oracle. Vous pouvez également mettre en place une solution de pagination de sorte que le résultat de chaque appel soit suffisamment petit.

Autres conseils

Vous avez mentionné que vos procédures stockées prennent beaucoup de temps. La majorité du temps est-il utilisé pendant le processus de sélection des lignes de la base de données ou de renvoi des lignes à l'appelant?

Si c’est le dernier cas, vous pouvez peut-être créer une version miroir de votre SP qui obtient simplement le nombre au lieu des lignes réelles. Si c’est le cas, eh bien, vous ne pouvez pas vraiment en faire beaucoup car c’est le fait de trouver les lignes éligibles qui est lent.

créer un proc stocké pour compter les lignes en premier.

SELECT COUNT (*) FROM table

Sauf si un aspect de la logique commerciale de votre application permet de calculer cela, non. La base de données devra faire tout le compte où & amp; rejoindre la logique pour comprendre comment les lignes de lignes, et c'est la grande majorité du temps passé dans le SP.

Vous ne pouvez pas obtenir le nombre de lignes d'une procédure sans l'exécuter.

Vous pouvez créer une procédure différente qui accepte les mêmes paramètres, dans le but de vous indiquer le nombre de lignes que l'autre procédure doit renvoyer. Toutefois, les étapes requises par cette procédure seraient normalement si semblables à celles de la procédure principale qu’elles devraient prendre à peu près aussi longtemps que l’exécution de la procédure principale.

Vous devez écrire une version différente de la procédure stockée pour obtenir un nombre de lignes. Celui-ci serait probablement beaucoup plus rapide car vous pourriez éliminer les tables de jonction sur lesquelles vous n'êtes pas filtré, supprimer les commandes, etc. Par exemple, si votre procédure stockée exécutait le code SQL, par exemple:

select firstname, lastname, email, orderdate  from 
customer inner join productorder on customer.customerid=productorder.productorderid
where orderdate>@orderdate order by lastname, firstname;

votre version de comptage serait quelque chose comme:

select count(*) from productorder where orderdate>@orderdate;

Pas en général.

Grâce à la connaissance du fonctionnement de la procédure stockée, vous pouvez obtenir une estimation ou un décompte précis (par exemple, si la table "principale" ou "de base" de la requête peut être rapidement calculés, mais ce sont des jointures complexes et / ou des résumés qui font remonter le temps).

Mais vous devez d'abord appeler le SP de comptage, puis le SP de données, ou vous pouvez envisager d'utiliser un SP de résultats multiples.

Cela peut prendre autant de temps pour obtenir un nombre de lignes que pour obtenir les données réelles. Je ne recommanderais donc pas d'effectuer un nombre dans la plupart des cas.

Quelques possibilités:

1) SQL Server expose-t-il ses résultats de l’optimiseur de requêtes d’une certaine manière? c.-à-d. pouvez-vous analyser la requête puis obtenir une estimation du nombre de lignes? (Je ne connais pas SQL Server).

2) Peut-être qu’en fonction des critères définis par l’utilisateur, vous pouvez effectuer vos propres estimations. Par exemple, si l'utilisateur entre "S%" dans le champ du nom de famille du client pour interroger les commandes, vous pouvez déterminer que cela correspond à 7% (disons) des enregistrements client et extrapoler le fait que la requête peut renvoyer 7% des enregistrements de commandes.

En reprenant ce que Tony Andrews a dit dans sa réponse, vous pouvez obtenir un plan de requête estimé de l'appel à votre requête avec:

SET showplan_text OFF
GO
SET showplan_all on
GO
--Replace with call you your stored procedure
select * from MyTable
GO 
SET showplan_all ofF
GO

Ceci devrait renvoyer une ou plusieurs tables qui vous permettront d'obtenir le nombre estimé de lignes de votre requête.

Vous devez analyser le jeu de données renvoyé pour déterminer ce qu'est une clé primaire logique (significative) pour le jeu de résultats renvoyé. En général, cela SERA bien plus rapide que la procédure complète, car le serveur ne construit pas de jeu de résultats à partir de données de toutes les colonnes de chaque ligne de chaque table, il compte simplement les lignes ... En général, il se peut même Pour ce faire, il est peut-être nécessaire de compter les noeuds d'indexation.

Ensuite, écrivez une autre instruction SQL qui n'inclut que les tables nécessaires à la génération de ces colonnes de clé (espérons qu'il s'agisse d'un sous-ensemble des tables de la requête principale), ainsi que la même clause where avec les mêmes valeurs de prédicat de filtrage ...

Ajoutez ensuite un autre paramètre facultatif au processus stocké appelé, par exemple, @CountsOnly, avec la valeur par défaut false (0), de la même manière ...

Alter Procedure <storedProcName>
@param1 Type, 
-- Other current params
@CountsOnly TinyInt = 0
As
Set NoCount On

   If @CountsOnly = 1
       Select Count(*) 
       From TableA A 
          Join TableB B On   etc. etc...
       Where < here put all Filtering predicates >

   Else
      <Here put old SQL That returns complete resultset with all data>

  Return 0

Vous pouvez alors simplement appeler le même processus stocké avec @CountsOnly défini sur égal à 1 pour obtenir uniquement le nombre d'enregistrements. L'ancien code qui appelle le proc fonctionnerait toujours comme avant, puisque la valeur du paramètre est définie sur false (0) par défaut, s'il n'est pas inclus

Il est au moins techniquement possible d’exécuter une procédure qui place le jeu de résultats dans une table temporaire. Ensuite, vous pouvez trouver le nombre de lignes avant de déplacer les données du serveur vers l’application et éviter de devoir créer deux fois le jeu de résultats.

Mais je doute que cela en vaille la peine, à moins que la création de l'ensemble de résultats ne prenne beaucoup de temps. Dans ce cas, la taille de la table temporaire risque de poser problème. Le temps nécessaire pour déplacer la grande table sur le réseau sera presque certainement le temps nécessaire pour la créer.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top