web-dev-qa-db-fra.com

Existe-t-il quelque chose de plus rapide que SqlDataReader dans .NET?

J'ai besoin de charger une colonne de chaînes de la table sur SqlServer dans le tableau en mémoire en utilisant C #. Existe-t-il un moyen plus rapide que d'ouvrir SqlDataReader et de le parcourir. Le tableau est grand et le temps est critique.

EDIT J'essaie de construire .dll et de l'utiliser sur le serveur pour certaines opérations sur la base de données. Mais c'est pour ralentir pour l'instant. Si c'est plus rapide que je dois repenser la base de données. J'ai du mal à trouver une solution pour accélérer les choses.

39
watbywbarif

Lecteur de données

À propos de l'accès le plus rapide que vous obtiendrez à SQL est avec le SqlDataReader .

Profilez-le

Cela vaut la peine de déterminer où se situe votre problème de performances. Habituellement, lorsque vous pensez que le problème de performances est, il s'avère que tout est faux après l'avoir profilé.

Par exemple, cela pourrait être:

  1. Le temps ... la requête prend pour s'exécuter
  2. Le temps ... les données prennent pour être copiées à travers la frontière du réseau/processus
  3. Le temps ... .Net prend pour charger les données en mémoire
  4. Le temps ... votre code prend pour en faire quelque chose

Le profilage de chacun d'eux isolément vous donnera une meilleure idée de l'endroit où se trouve votre goulot d'étranglement. Pour profiler votre code, il y a un excellent article de Microsoft

Cachez-le

La chose à regarder pour améliorer les performances est de déterminer si vous devez charger toutes ces données à chaque fois. La liste (ou une partie de celle-ci) peut-elle être mise en cache? Jetez un œil au nouvel espace de noms System.Runtime.Caching .

Réécrire en T-SQL

Si vous effectuez des opérations purement de données (comme le suggère votre question), vous pouvez réécrire votre code qui utilise les données pour être T-SQL et s'exécuter de manière native sur SQL. Cela peut être beaucoup plus rapide, car vous travaillerez directement avec les données et ne les déplacerez pas.

Si votre code a beaucoup de logique procédurale nécessaire, vous pouvez essayer de mélanger T-SQL avec Intégration CLR vous donnant les avantages des deux mondes.

Cela dépend beaucoup de la complexité (ou de la nature plus procédurale) de votre logique.

Si tout le reste échoue

Si toutes les zones sont optimales (ou aussi proches que), et votre conception est sans faille. Je n'entrerais même pas dans la micro-optimisation, je voudrais juste jeter du matériel dessus .

Quel matériel? Essayez le moniteur de fiabilité et de performances pour savoir où se trouve le goulot de la bouteille. L'endroit le plus probable pour le problème que vous décrivez HDD ou RAM.

51
badbod99

Si SqlDataReader n'est pas assez rapide, vous devriez peut-être stocker vos données ailleurs, comme un cache (en mémoire).

19
Steven

Non, ce n'est pas seulement le moyen le plus rapide, c'est le SEUL (!) Moyen. Tous les autres mécanismes utilisent de toute façon un DataReader.

17
TomTom

Je soupçonne que SqlDataReader est à peu près aussi bon que vous allez en avoir.

9
LukeH

SqlDataReader est le moyen le plus rapide. Assurez-vous d'utiliser les méthodes get by ordinal plutôt que get by column name. par exemple. GetString (1);

Il est également utile d'expérimenter MinPoolSize dans la chaîne de connexion afin qu'il y ait toujours des connexions dans le pool.

5
softveda

Le SqlDataReader sera le moyen le plus rapide. Optimisez son utilisation, en utilisant la méthode Getxxx appropriée, qui prend un ordinal comme paramètre.

Si ce n'est pas assez rapide, voyez si vous pouvez modifier votre requête. Mettez un index de couverture sur la ou les colonnes que vous souhaitez récupérer. Ce faisant, Sql Server n'a qu'à lire l'index et n'a pas à accéder directement à la table pour récupérer toutes les informations requises.

3
Frederik Gheysels

Qu'en est-il de la transformation d'une colonne de lignes en une ligne de colonnes et de n'avoir qu'une seule ligne à lire? SqlDataReader a une optimisation pour lire une seule ligne (System.Data.CommandBehavior.SingleRow argument de ExecuteReader), donc cela peut peut-être améliorer un peu la vitesse.

Je vois plusieurs avantages:

  • Amélioration d'une seule rangée,
  • Pas besoin d'accéder à un tableau à chaque itération (reader[0]),
  • Le clonage d'un tableau (reader) sur un autre peut être plus rapide que de parcourir des éléments et de les ajouter à un nouveau tableau.

D'un autre côté, il a pour inconvénient de forcer la base de données SQL à faire plus de travail.

2
Arseni Mourzenko

Quelques éléments au niveau de la surface à considérer qui peuvent affecter la vitesse (en plus d'un lecteur de données):

  1. Optimisation des requêtes de base de données
    • OrderBy est cher
    • Distinct est cher
    • RowCount coûte cher
    • GroupBy est cher
    • etc. Parfois, vous ne pouvez pas vivre sans ces choses, mais si vous pouvez gérer certaines de ces choses dans votre code C # à la place, cela peut être plus rapide.
  2. Indexation de la table de base de données (pour commencer, les champs de votre clause WHERE sont-ils indexés?)
  3. Database Table DataTypes (utilisez-vous le plus petit possible, étant donné les données?)
  4. Pourquoi convertissez-vous le lecteur de données en un tableau?
    • par exemple, cela servirait-il aussi bien à créer un adaptateur/une table de données que vous n'auriez alors pas besoin de convertir en tableau?
  5. Avez-vous étudié Entity Framework? (peut être plus lent ... mais si vous n'avez pas d'options, cela pourrait valoir la peine de vérifier juste pour vous en assurer)

Juste des pensées aléatoires. Je ne sais pas ce qui pourrait vous aider dans votre situation.

1
おたく

"Fournit un moyen de lire un flux de lignes en avant uniquement à partir d'une base de données SQL Server" C'est l'utilisation de SqlDataReader de MSDN. La structure de données derrière SqlDataReder ne permet que la lecture en avant, elle est optimisée pour lire les données dans une seule direction. À mon avis, je veux utiliser SqlDataReader que DataSet pour une lecture simple des données.

1
coolkid

Vous disposez de 4 ensembles de frais généraux - Accès au disque - Code .net (cpu) - Code serveur SQL (cpu) - Temps de basculer entre le code managé et non managé (cpu)

Est d'abord

select * where column = “junk” 

assez rapide pour vous, sinon la seule solution est de rendre le disque plus rapide. (Vous pouvez obtenir des données de SQL Server plus rapidement qu'il ne peut les lire)

Vous pourrez peut-être définir une fonction Sql Server en C # puis exécuter la fonction sur la colonne; désolé, je ne sais pas comment faire. Cela peut être plus rapide qu'un lecteur de données.

Si vous avez plusieurs processeurs et que vous connaissez une valeur au milieu du tableau, vous pouvez essayer d'utiliser plusieurs threads.

Vous pourrez peut-être écrire du TSQL qui combine toutes les chaînes en une seule chaîne en utilisant un séparateur que vous savez sûr. Ensuite, divisez à nouveau la chaîne en C #. Cela réduira le nombre d'aller-retour entre le code géré et non géré.

1
Ian Ringrose

Si la réactivité est un problème de chargement d'un grand nombre de données, envisagez d'utiliser les méthodes asynchrones - BeginReader.

Je l'utilise tout le temps pour remplir de grands éléments d'interface graphique en arrière-plan pendant que l'application continue de répondre.

Vous n'avez pas précisé exactement la taille de ces données, ni pourquoi vous les chargez toutes dans un tableau.

Souvent, pour de grandes quantités de données, vous souhaiterez peut-être les laisser dans la base de données ou laisser la base de données faire le gros du travail. Mais nous aurions besoin de savoir quel type de traitement que vous faites qui nécessite tout cela dans un tableau à la fois.

0
Cade Roux