D'accord, j'ai besoin de mettre en cache un sous-ensemble relativement petit de données rarement modifiées pour éviter d'interroger la base de données aussi fréquemment pour des raisons de performances. Ces données sont fortement utilisées en lecture seule, car elles sont souvent référencées par un ensemble de données beaucoup plus volumineux dans d'autres tables.
J'ai écrit une classe qui aura la capacité de stocker en mémoire la totalité des deux tables en question tout en écoutant les modifications de validation en conjonction avec un mécanisme de rappel sécurisé pour la mise à jour des objets en cache.
Mon implémentation actuelle a deux std::vectors
un pour les éléments de chaque table. La classe fournit à la fois un accès à l'intégralité de chaque vecteur ainsi que des méthodes pratiques pour rechercher un élément spécifique de données de table via std::find
, std::find_if
, etc.
Est-ce que quelqu'un sait si utiliser std::list
, std::set
ou std::map
au-dessus de std::vector
serait préférable? La plupart du temps, c'est ce qui sera demandé à ces conteneurs après avoir été renseigné une fois à partir de la base de données lorsqu'une nouvelle connexion est établie.
Je suis également ouvert à l'utilisation des fonctionnalités C++ 0x prises en charge par VS2010 ou Boost.
Pour rechercher une valeur particulière, avec std::set
et std::map
cela prend O (journal N), alors qu'avec les deux autres, cela prend O(N); Donc, std::set
ou std::map
sont probablement meilleurs. Puisque vous avez accès à C++ 0x, vous pouvez également utiliser std::unordered_set
ou std::unordered_map
qui prennent un temps constant en moyenne.
Pour find_if
, il y a peu de différence entre eux, car il faut un prédicat arbitraire et les conteneurs ne peuvent pas optimiser de manière arbitraire, bien sûr.
Toutefois, si vous appelez fréquemment find_if
avec un prédicat donné, vous pouvez optimiser vous-même: utilisez un std::map
ou std::set
avec un comparateur personnalisé ou des clés spéciales et utilisez plutôt find
.
Un vecteur trié utilisant std::lower_bound
peut être aussi rapide que std::set
si vous ne mettez pas à jour très souvent. ils sont tous les deux O (log n). Cela vaut la peine d'essayer les deux pour voir ce qui convient le mieux à votre situation.
Étant donné que parmi vos exigences (étendues), vous devez effectuer des recherches dans plusieurs champs, je vous indiquerais Boost.MultiIndex.
Cette bibliothèque Boost vous permet de construire one container (avec un seul exemple de chaque élément qu’il contient) et de l’indexer sur un nombre arbitraire d’index. Il vous permet également de préciser les index à utiliser.
Pour déterminer le type d’indice à utiliser, vous aurez besoin de points de repère étendus. 500
est un nombre relativement faible d'entrées, donc les facteurs constants ne jouent pas bien. De plus, il peut y avoir une différence notable entre les utilisations à un seul thread et les multi-threads (la plupart des implémentations de table de hachage peuvent s’effondrer sur l’utilisation de MT car elles n’utilisent pas le rehachage linéaire, et ainsi un seul thread finit par réhase table, bloquant toutes les autres).
Je recommanderais un index trié (skip-list type, si possible) pour prendre en charge les demandes de plage (tous les noms commençant par Abc
?) Si la différence de performances est soit imperceptible, soit simplement indifférente.
Essaye-le. C’est très simple, les conteneurs sont presque interchangeables en LIST.
Si vous souhaitez uniquement rechercher des valeurs distinctes, une colonne spécifique du tableau, std::hash
est le plus rapide.
Si vous voulez pouvoir utiliser plusieurs prédicats différents, vous aurez besoin d'une sorte de structure d'index. Pour ce faire, vous pouvez étendre votre approche basée sur les vecteurs à l'aide de plusieurs tables de hachage ou cartes, une pour chaque champ à rechercher, où la valeur est un index dans le vecteur ou un pointeur direct sur l'élément du vecteur.
Pour aller plus loin, si vous voulez pouvoir rechercher des plages, telles que toutes les occasions ayant une date en juillet, vous avez besoin d'une structure de données ordonnée, où vous pouvez extraire une plage.
Non stl, mais un conteneur commercial c ++ est un conteneur abax contenant O(1) dans les fonctions de recherche, suppression, modification, O(logn).