Question

Récemment, j'ai dû traiter des données très lourdes avec des données stockées dans un DataSet. C'était assez lourd pour utiliser un outil permettant d'identifier certains goulots d'étranglement dans mon code. Lorsque j’ai analysé les goulots d’étranglement, j’ai remarqué que, même si les recherches dans DataSet n’étaient pas très lentes (elles ne constituaient pas le goulot d’étranglement), elles étaient plus lentes que prévu. J'ai toujours supposé que DataSets utilisait une sorte d'implémentation de style HashTable qui ferait des recherches O (1) (ou du moins c'est ce que je pense que sont les HashTables). La vitesse de mes recherches semblait être nettement plus lente que cela.

Je me demandais si quelqu'un qui serait au courant de la mise en œuvre de la classe DataSet de .NET voudrait partager ce qu'il sait.

Si je fais quelque chose comme ça:

DataTable dt = new DataTable();
if(dt.Columns.Contains("SomeColumn"))
{
    object o = dt.Rows[0]["SomeColumn"];
}

Quelle est la rapidité du temps de recherche de la méthode Contains (...) et de récupération de la valeur à stocker dans Object o ? J'aurais pensé que ce serait très rapide comme un HashTable (en supposant que ce que je comprends de HashTables est correct), mais cela ne semble pas être le cas ...

J'ai écrit ce code de la mémoire afin que certaines choses ne soient pas "syntaxiquement correctes".

Était-ce utile?

La solution

Via Reflector , les étapes à suivre pour DataRow [" ColumnName "] sont les suivantes:

  1. Obtenez le DataColumn à partir de ColumnName. Utilise le DataColumnCollection [" ColumnName "de la ligne. En interne, DataColumnCollection stocke ses DataColumns dans un Hastable. O (1)
  2. Récupère l'index de ligne du DataRow. L'index est stocké dans un membre interne. O (1)
  3. Obtenez la valeur de DataColumn à l'index en utilisant DataColumn [index]. DataColumn stocke ses données dans un membre System.Data.Common.DataStorage (internal, abstract):

    renvoyer dataColumnInstance._storage.Get (recordIndex);

    Un exemple d'implémentation concrète est System.Data.Common.StringStorage (interne, scellé). StringStorage (et les autres DataStorages concrets que j'ai cochés) stocke leurs valeurs dans un tableau. Get (recordIndex) récupère simplement l'objet dans le tableau de valeurs à recordIndex. O (1)

Donc globalement, vous êtes O (1), mais cela ne signifie pas que le hachage et l’appel de fonction pendant l’opération sont sans coût. Cela signifie simplement que cela ne coûte pas plus cher avec l'augmentation du nombre de DataRows ou de DataColumns.

Il est intéressant de noter que DataStorage utilise un tableau pour les valeurs. Vous ne pouvez pas imaginer qu'il soit facile de reconstruire lorsque vous ajoutez ou supprimez des lignes.

Autres conseils

En fait, il est recommandé d’utiliser un entier pour référencer une colonne, ce qui peut améliorer considérablement les performances. Pour que les choses restent gérables, vous pouvez déclarer un entier constant. Donc, au lieu de ce que vous avez fait, vous pourriez faire

const int SomeTable_SomeColumn = 0;

DataTable dt = new DataTable();
if(dt.Columns.Contains(SomeTable_SomeColumn))
{
    object o = dt.Rows[0][SomeTable_SomeColumn];
}

J'imagine que toutes les recherches seraient O (n), car je ne pense pas qu'elles utiliseraient un type de hashtable, mais utiliseraient plutôt un tableau pour trouver des lignes et des colonnes.

En fait, je pense que les noms des colonnes sont stockés dans une table de hachage. Devrait être O (1) ou une recherche constante pour les recherches sensibles à la casse. S'il devait regarder à travers chacun d'eux, alors bien sûr, ce serait O (n).

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