Je cherche à stocker une liste triée dans une base de données. Je souhaite effectuer efficacement les opérations suivantes.
- Insert (x) - Insère l'enregistrement x dans la table
- Supprimer (x) - Supprimer l'enregistrement x de la table
- Before (x, n) - Renvoie les enregistrements 'n' précédant l'enregistrement x dans la liste triée.
- After (x, n) - Renvoie les enregistrements 'n' qui succèdent à l'enregistrement x dans la liste triée.
- Premier (n) - Renvoie les premiers n enregistrements de la liste triée.
- Dernier (n) - Renvoie les derniers n enregistrements de la liste triée.
- Comparer (x, y) - Deux enregistrements x et y de la table, trouver si x> y.
La méthode simple à laquelle je pouvais penser est de stocker une sorte d'attribut 'rang' dans la table et d'interroger en triant sur cet attribut. Mais dans cette méthode, insérer / modifier un enregistrement avec un rang devient une opération coûteuse. Y a-t-il une meilleure méthode?
Plus précisément, je cherche à implémenter la table en utilisant SimpleDB d'Amazon. Mais une réponse générale à une base de données relationnelle devrait également être utile.
Mise à jour sur le profil de charge:
Comme je prévois cela pour une application Web, cela dépend du nombre d'utilisateurs qui l'utilisent.
S'il y a 100 000 utilisateurs actifs (super optimisme: P), alors mon estimation très approximative par jour serait
500 000 sélections, 100 000 insertions et suppressions, 500 000 mises à jour
Je m'attendrais à ce que la table atteigne 500k au total.
Je cherche à optimiser les opérations de mise à jour, d’insertion et de comparaison. Le classement des objets changera constamment et je dois tenir le tableau à jour.
la source
Réponses:
Si le classement n'est pas complètement arbitraire, mais qu'il peut être déduit d'une autre propriété (par exemple, nom, score du joueur, etc.), examinez attentivement la réponse de Joel .
S'il s'agit d' une propriété arbitraire de vos données, elle doit être stockée sous forme de colonne dans votre table d'enregistrements. En supposant que SimpleDB d'Amazon soit similaire au SGBDR classique, vous pouvez alors indexer cette colonne et satisfaire rapidement toutes vos requêtes ci-dessus avec la stratégie d'indexation appropriée. Ceci est normal pour un SGBDR.
Étant donné que vous vous attendez à une activité d'insertion et de mise à jour élevée, mais également à une activité de lecture relativement élevée, je vous recommande de procéder comme suit:
INCLUDE
rang et un rang, ou simplement un enregistrement si vous avez mis en cluster sur un rang) satisferaient la requête 7.FILLFACTOR
dans SQL Server). Ceci est particulièrement important si vous vous regroupez sur un rang.Si vous vous attendez à plus de 100 000 lectures sur une table de taille supérieure à 100 000, je vous déconseille d'utiliser la méthode de la liste chaînée. Il ne sera pas adapté à ces tailles.
la source
FILLFACTOR
vous constaterez qu'il est essentiellement conçu pour créer cet espace supplémentaire pour les enregistrements d'un index, tout comme les espaces de classement que j'ai décrits créent un espace pour les modifications de classement et les insertions.J'utilise généralement la méthode "rang" que vous décrivez. Plutôt que de perdre du temps avec la mise à jour des lignes lorsque des éléments devaient être réorganisés, j'ai souvent réussi à supprimer tous les enregistrements de la liste et à réinsérer de nouveaux éléments dans le bon ordre. Cette méthode est clairement optimisée pour la récupération.
Une autre approche consisterait à modéliser les enregistrements sous forme de liste chaînée en utilisant une colonne de clé étrangère réflexive "prédécesseur" sur la table:
Vous pouvez facilement récupérer une liste et ajouter et supprimer des éléments avec un léger surcoût, mais il sera difficile de sortir les enregistrements dans le bon ordre. Peut-être y a-t-il une façon intelligente de le faire en une seule requête, probablement avec beaucoup de jointures de table avec alias.
J'utilise souvent cette dernière approche lorsque je modélise une relation en arborescence (catégories, dossiers, ensembles et sous-ensembles). J'ai généralement eu une fonction récursive pour reconstruire l'arborescence complète dans mon application.
la source
Je pense que la chose à faire est de stocker la ou les propriétés qui sont utilisées pour calculer le rang , puis de construire un index sur elles. Plutôt que d'essayer de forcer la base de données à stocker physiquement les données dans un ordre hiérarchisé ou à l'aide d'une liste chaînée gérée manuellement, pourquoi ne pas laisser le moteur de base de données faire ce pour quoi il a été conçu?
la source
Ce sont les limitations d'un système non-SGBDR tel que simpleDB. Les fonctionnalités dont vous avez besoin ne peuvent pas être implémentées du côté de la base de données dans simpleDB, elles doivent être implémentées du côté de la programmation / de l'application.
Pour un SGBDR
SQL server
, les fonctionnalités dont vous avez besoin sont rudimentaires pour l’index clusterisé.Before (x, n) - Renvoie les enregistrements 'n' précédant l'enregistrement x dans la liste triée. > Sélectionnez les n premiers résultats où x est inférieur à valeur et commande par clause.
After (x, n) - Renvoie les enregistrements 'n' qui succèdent à l'enregistrement x dans la liste triée. > Sélectionnez les n premiers résultats où x est supérieur à valeur et commande par clause.
Premier (n) - Renvoie les premiers n enregistrements de la liste triée. > Sélectionnez les n premiers résultats.
Dernier (n) - Renvoie les derniers n enregistrements de la liste triée. > Sélectionnez les n premiers résultats après ordre en desc.
la source
Voici ce que j'avais l'habitude de re-classer ma table Postgres après chaque insertion:
Pour mon cas d'utilisation, la performance n'est pas une préoccupation, mais il est important de pouvoir compter sur sa capacité à ne jamais casser ou à agir bizarrement.
la source