2009-02-04 7 views
4

J'ai une question concernant les performances de SQL. Je vais illustrer mon problème avec le pseudocode. Je me demande qui va mieux préformer et de combien? Dites pour 10 articles, sur chaque chargement de page. En .NET. Est-ce que c'est beaucoup plus rapide? un petit peu plus vite? Une différence non perceptible sur SQL?SQL Performance Question

foreach(item in mylist) { 
CallSQLStoredProc(item.id); 
} 

vs

int[] ids; // array of ids 
CallSQLStoredProc(ids) // stored procedure returns more than one row for each id 

Répondre

11

La deuxième option sera certainement plus rapide car il est un réseau unique aller-retour, ainsi qu'un seul appel de SP.

0

À chaque chargement de page ou lors du premier chargement de la page? Je ne voudrais pas faire cela pour chaque publication dans une page ASP.NET.

Pour répondre plus directement à votre question, si vous êtes en mesure d'obtenir plusieurs enregistrements en envoyant plusieurs ID, faites-le. Plus efficace et plus évolutif si jamais vous avez besoin de plus de 10 éléments.

0

tout dépend comment le proc est codé, si vous passez 10 points dans le 2ème proc et que proc utilise alors un curseur pour obtenir les lignes puis le premier appel pourrait être plus rapide

2

Definetly la seconde, variable d'environ 10x plus vite à un peu plus vite. Si tout ce que vous faites avec les ID peut être fait dans une opération de jeu, vous obtiendrez plusieurs fois le gain de performance que d'appeler individuellement le SP.

J'ai régulièrement procs qui ressemblent à:

create procedure proc (@ids varchar(max)) as 
select * from users_tbl u 
inner join spiltCSVs(@ids) c 
    on c.id = u.id 
--so on and so forth 

C'est une opération à base de jeu; par opposition à la méthode procédurale utilisant un curseur dans le proc, ou en utilisant la boucle for pour itérer l'appel de la procédure avec un identifiant individuel.

+0

quel DB utilisez-vous? Je recherche cette fonction "spiltCSVs" dans SQL Server. Google "spiltCSVs" renvoie-moi 1 résultat :-) –

+0

C'est une fonction d'utilité chaque écrit eux-mêmes si nécessaire. http://stackoverflow.com/questions/314824/t-sql-opposite-to-string-concatenation-how-to-split-string-into-multiple-recor –

1

Comme cela ne rentre pas dans un commentaire pour la réponse ocdecio ...

Juste pour étendre là-dessus ... dans la plupart des systèmes que j'ai vu le trafic réseau est le facteur limitant de la performance (en supposant une base de données raisonnablement ajustée et un code frontal qui n'est pas absolument horrible). Même si votre serveur Web et votre serveur de base de données sont sur la même machine, la communication interprocess peut être un facteur limitant si vous avez des appels fréquents entre les deux.

0

Combien plus vite la seconde dépend vraiment d'un trop grand nombre de choses. La surcharge réseau peut être insignifiante par rapport à la taille de vos ensembles de résultats.

Il existe une autre alternative (qui devrait être plus rapide que l'une ou l'autre selon le comportement de verrouillage), à ​​savoir call all of them asynchronously - alors votre page peut effectivement se terminer lorsque la plus longue est terminée. Évidemment, cela nécessitera un codage supplémentaire.

Dans cet exemple, il n'y a qu'un seul préfixe SP. Nous supposons que les rendements SP soit un ensemble de lignes que le client sera divisé/processus ou plusieurs jeux de lignes:

int[] ids; // array of ids 
CallSQLStoredProc(ids) // stored procedure returns more than one row for each id 

Dans cet exemple, les frais généraux d'appel SP sont n fois l'appel unique.et les appels sont sérialisés:

foreach(item in mylist) { 
    CallSQLStoredProc(item.id); 
} 

Dans la troisième alternative:

foreach(item in mylist) { 
    StartSQLStoredProc(item.id); 
} 

// Continue building the page until you reach a point where you absolutely have to have the data 

wait(); 

Cela a encore les frais généraux d'appel n DB, mais l'amélioration de la performance peut dépendre de la capacité du serveur SQL et réseau afin de paralléliser la charge de travail. En outre, vous bénéficiez de la possibilité de démarrer SQL Server pendant la création de la page.

La seule solution SP peut encore gagner sur, en particulier si elle peut assembler un seul jeu de résultats avec une Union où le serveur SQL peut paralléliser la tâche. Cependant, si les ensembles de résultats ont des schémas séparés ou si l'UNION ne peut pas fonctionner correctement, une solution asynchrone SP multiple peut l'éliminer (et peut également tirer parti de la possibilité d'effectuer d'autres tâches dans la page).

+0

Si cela peut être fait de manière asynchrone, il peut alors être écrit pour être parallélisé par le moteur DB. Dans ce cas, l'appel unique sera toujours plus rapide. L'appel unique sera toujours plus rapide. – alyssackwan

+0

Malheureusement, les lots séparés dans les SP ne sont pas parallélisés par le DB. L'appel unique qui doit construire 10 ensembles de lignes et les retourner ensuite n'est pas garanti être plus rapide si vous pouvez diffuser 10 flux importants différents hors de la base de données simultanément. Je vais mettre à jour la réponse pour démontrer. –

0

L'itération de tout ce qui va toujours causer plus de frais généraux. Il n'y a pas beaucoup de situations où l'itération améliore les performances.

Mon conseil a toujours été d'éviter 2 choses dans la programmation:

  1. if then else statments
  2. itération

Vous aurez toujours des situations où vous utiliserez les deux, mais moins vous en utilisez plus le potentiel de votre application est plus rapide et plus fluide.

0

SI vous voulez l'évolutivité dans votre application, vous voulez utiliser la mise en cache autant que possible. Vous devez exécuter toutes les requêtes partagées une seule fois et stocker le résultat dans le cache.

Quant à votre requête, à condition que vous n'utilisez pas les curseurs dans la requête pour chaque ID, il doit être fourni plus rapidement que la latence du réseau a un impact significatif sur ce que vous faites. En cas de doute, mesurez. J'ai été très surpris à plusieurs reprises lorsque j'ai mis en place le chronométrage de mes fonctions pour voir combien de temps les choses ont pris.

Dans .net System.Diagnostics.StopWatch est votre ami :).