web-dev-qa-db-fra.com

Stocker des tableaux d'entiers dans la base de données (pour une sélection efficace)

Je crée une base de données qui stockera 100 000 (et probablement plus à l'avenir) des utilisateurs. Bien que cela arrive évidemment dans une table avec 1 ligne par utilisateur, chaque utilisateur peut (et la volonté) stocker des centaines d'articles. Dans le langage de programmation, cela signifierait que l'utilisateur dispose de 2 tableaux (ou d'une matrice à 2 dimensions) d'entiers: une colonne pour la colonne ItemID et une colonne pour les quantités.

Mon instinct me dise à créer une table pour contenir tous ces articles, avec des lignes telles que (userid, élémentId, montant). Cependant, cela entraînerait une énorme table. 200.000 utilisateurs avec 250 articles chacun ... c'est 50 millions d'entrées dans une seule table. Ceci, ainsi que le fait que la table subira un changement continu et rapide, effraie-moi. (Quelle vitesse? J'estime jusqu'à 100 modifications par seconde.)

En règle générale, il y aura n'importe où entre 100 et 2000 utilisateurs, tous ajoutant et supprimant des éléments et modifieront les montants. Ces actions peuvent et se produiront dans le code de programmation. Cela irait comme suit:

  • Séance Démarre l'utilisateur, programme Charge tous les éléments de l'utilisateur de la base de données
  • L'utilisateur modifie la liste des éléments
  • Toutes les quelques minutes, les modifications sont enregistrées dans la base de données
  • Lorsque l'utilisateur met fin à la session, il est également enregistré dans la base de données.

Il convient de noter qu'il y a un maximum au nombre d'articles qu'un utilisateur peut stocker.

Y a-t-il des alternatives à utiliser une table séparée? Peut-être enregistrer les valeurs dans une chaîne de texte formatée? Ou est-ce l'une des instances où l'utilisation d'une base de données MySQL est en réalité une mauvaise idée ™?

Merci pour votre temps et vos idées.

5
Rapsey

Les SGBDM ont été construits pour gérer ce type de relations et d'opérations. De plus, le stockage des utilisateurs et des éléments séparément aidera séparément avec des rapports détaillés (par exemple: nombre d'éléments ajoutés aujourd'hui).

Avec des index optimisés, la lecture de nombreux articles par utilisateur n'est qu'une recherche. La table d'éléments peut être indexée pour stocker les éléments associés (par utilisateur) consécutivement, donnant ainsi à un tableau comme un scénario de lecture. Assurez-vous simplement d'utiliser le remplissage de la page pour permettre les futures mises à jour/inserts/suppressions.

Les SGBDR sont assez rapides et peuvent gérer des centaines de milliers d'opérations par seconde, ce qui peut donc ne pas être un problème. Lorsque vos articles sont sur une table différente, les mises à jour effectuées par article seront meilleures que si les éléments étaient stockés dans une colonne de texte (en tant que tableau) dans les mêmes lignes que l'utilisateur. Cela vous donnera des mises à jour plus rapides, une mémoire moindre requise pour l'opération, des verrous et des versions plus rapides (et vous ne pouvez pas avoir à verrouiller votre utilisateur respectif), de plus petites lues/écrit, etc.

6
StanleyJohns

Gardez les objets comme une table séparée. Vous avez besoin de temps de réponse rapide pour de nombreuses sessions simultanées. Si vous utilisez Oracle, vous pouvez faire un beau scénario de cache IMDB. Dans ce scénario, vous préchargez le cache pour un utilisateur à la connexion de connexion, rendant les lignes mises à jour dans des hautes fréquences dans la mémoire disponible. Pour que cela soit utilisé, vous avez besoin de Oracle 11Gr2. Voir Cache de base de données Oracle in-Memory Cela vous donne une solution très évolutive. Les temps de réponse peuvent être inférieurs à la milliseconde.

3
ik_zelf

MySQL n'aura aucun problème à gérer la charge de travail que vous suggérez. Tant que vous indexez correctement les tables et que mysql ajusté (la configuration par défaut devrait même aller bien pendant un moment))

Comme mentionné, vous voudrez que InnoDB - et vous voudrez investir un peu de temps à apprendre à quel point travaille InnoDB.

MySQL n'a pas de problème de traitement de plus de 1000 QP et de tables avec des centaines de millions de lignes.

2
thinice

Si vous allez utiliser MySQL pour cette application, tout cela signifie à l'écart de Myisam !!!

Tous les inserts, mises à jour et suppressions sur les tables Myisam effectueront une serrure de table complète avant d'exécuter la mise à jour sur la table, même si vous mettez à jour une seule ligne.

Cela facilite l'utilisation d'innoDB beaucoup plus propice, car il propose un verrouillage de rangée et un tampon innodub à la fois des données et des pages d'index. Si vous utilisez un grand pool de tampons InnoDb et que les utilisateurs sont des mises à jour systématiques, les utilisateurs seront déjà mis en cache et les données seront systématiquement rougées sur le disque à intervalles réguliers.

Une fois que vous avez des données chargées, vous pouvez exécuter cette formule pour estimer (ou deviny) Quelle est la taille d'un pool de tampons InnoDB auxquels vous aurez besoin de:

SELECT
CONCAT(ROUND(KBS/POWER(1024,IF(PowerOfTwo<0,0,IF(PowerOfTwo>3,0,PowerOfTwo)))+0.49999),
SUBSTR(' KMG',IF(PowerOfTwo<0,0,IF(PowerOfTwo>3,0,PowerOfTwo))+1,1)) recommended_innodb_buffer_pool_size
FROM (SELECT SUM(data_length+index_length) KBS FROM information_schema.tables
WHERE engine='InnoDB') A,(SELECT 2 PowerOfTwo) B;

Cela lira des statistiques sur la consommation de disques de disques par Innodb et imprimera la taille suggérée en mégaoctets et elle permettra de répondre à 4 Go. Vous pouvez utiliser de grandes valeurs pour innodb_buffer_pool_size si vous utilisez un système d'exploitation 64 bits. Cas et point: j'ai un client avec une piscine tampon de 162 Go sur 3 serveurs DB (MySQL 5.5 avec Dual Hexacore [pas une faute de frappe, 12 cpus]).

  • Utiliser (sélectionnez 0 Poweroftwo) pour le voir en octets
  • Utiliser (sélectionnez 1 Poweroftwo) pour le voir en kilo-octets
  • Utilisez (sélectionnez 2 Poweroftwo) pour le voir en mégaoctets
  • Utiliser (sélectionnez 3 Poweroftwo) pour le voir dans GigaBytes

Techniquement, Poweroftwo est vraiment le pouvoir de 1024 pour l'affichage des octets.

1
RolandoMySQLDBA