Je travaille sur une application qui implique une exécution très élevée des requêtes de mise à jour / sélection dans la base de données.
J'ai une table de base (A) qui aura environ 500 enregistrements pour une entité pendant une journée. Et pour chaque utilisateur du système, une variation de cette entité est créée en fonction de certaines des préférences de l'utilisateur et elles sont stockées dans une autre table (B). Cela se fait par un travail cron qui s'exécute à minuit tous les jours.
Donc, s'il y a 10 000 utilisateurs et 500 enregistrements dans le tableau A, il y aura 5 millions d'enregistrements dans le tableau B pour ce jour. Je garde toujours les données pendant une journée dans ces tableaux et à minuit j'archive les données historiques sur HBase. Cette configuration fonctionne bien et je n'ai aucun problème de performances jusqu'à présent.
Il y a eu un certain changement dans les exigences de l'entreprise ces derniers temps et maintenant certains attributs dans la table de base A (pour 15-20 enregistrements) changeront toutes les 20 secondes et sur cette base, je dois recalculer certaines valeurs pour tous ces enregistrements de variation dans la table B pour tous les utilisateurs. Même si seulement 20 enregistrements principaux changent, je dois recalculer et mettre à jour 200 000 enregistrements utilisateur, ce qui prend plus de 20 secondes et d'ici là, la prochaine mise à jour se produit, ce qui entraîne la mise en file d'attente de toutes les requêtes Select. Je reçois environ 3 requêtes get / 5 secondes des utilisateurs en ligne, ce qui entraîne 6-9 requêtes Select. Pour répondre à une demande d'api, j'utilise toujours les champs du tableau B.
Je peux acheter plus de puissance de traitement et résoudre cette situation, mais je suis intéressé par un système correctement mis à l'échelle pouvant gérer même un million d'utilisateurs.
Quelqu'un ici peut-il suggérer une meilleure alternative? La base de données relationnelle nosql + m'aide-t-elle ici? Existe-t-il des plates-formes / banques de données qui me permettront de mettre à jour les données fréquemment sans verrouillage et en même temps me donneront la flexibilité d'exécuter des requêtes sélectionnées sur divers champs d'une entité?
la source
Réponses:
On dirait que la table
B
est une sorte de cache. Mais ce genre de cache qui réduit la productivité ..Même si vous avez 25 requêtes par seconde, vous pouvez refuser l'utilisation de la table
B
et calculer la réponse pour chaque requête.Quoi qu'il en soit , si vous avez 30 secondes de retard sur la mise à jour de 20 enregistrements - c'est un échec dans une architecture logicielle (je me trompe, si votre base de données calcule les 10 ^ 100 premiers signes de PI pour chaque enregistrement).
Comme je le sais, une base de données relationnelle sans vilaines requêtes SQL, avec des index et avec moins de 1 000 000 d'enregistrements fonctionnera parfaitement pour presque toutes les requêtes.
Essayez de refuser l'utilisation de la table
B
et ajoutez des index appropriés à votre tableA
(la plupart des bases de données modernes ont un outil d'aide). Ensuite: essayez d'optimiser la structure des données (tableA
) et une requête (en utilisant un analyseur de requêtes ou avec des experts SQL) pour accélérer le calcul. Si vous ne mettez à jour que 20 enregistrements - l'existence d'index ne nuira pas à la productivité d'un processus de mise à jour , mais améliore considérablement la vitesse de sélection .la source
La question est vraiment de savoir quel système calcule l'enregistrement à insérer dans B et la taille des données B.
Toute base de données (par exemple MSSQL) devrait être capable de gérer le volume d'insertions dont vous parlez sans problème en supposant que l'objet n'est pas énorme.
Les mises à jour peuvent être un problème plus difficile, mais avec l'indexation et le verrouillage appropriés, encore une fois, cela ne devrait pas être un gros problème.
99% du temps quand je vois un problème comme celui-ci, c'est parce que l'enregistrement B est calculé par un proc stocké. Cela met toute la charge sur le serveur db
Si tel est le cas, la solution consiste à déplacer ce code vers un service hors ligne qui peut être appelé via un système de mise en file d'attente.
Ainsi, votre message de mise à jour A déclencherait un processus de travail qui traverserait les utilisateurs et créerait un message de mise à jour B pour chaque utilisateur
Un deuxième processus de travail B ramasserait la mise à jour de l'utilisateur X avec les données Un événement créerait l'enregistrement B et mettrait à jour la base de données
Cela peut être mis à l'échelle en ajoutant plus de boîtes avec des travailleurs de file d'attente, afin que vous ayez de plus en plus de puissance de traitement derrière le calcul, laissant votre base de données libre de se concentrer sur les mises à jour et les sélections.
vous pouvez optimiser davantage en séparant les sélections des mises à jour / insertions. avoir une nouvelle base de données qui obtient toutes les demandes de sélection en tant qu'esclave de réplication, l'ancienne base de données qui obtient toutes les mises à jour.
la source
Si vous utilisez Amazon, je considérerais DynamoDB. Il est basé sur la mémoire flash. Voici un lien vers celui-ci: https://aws.amazon.com/dynamodb/ .
Quels types de SGBDR utilisez-vous? Vous pouvez peut-être augmenter les performances en utilisant un UDF ou un champ calculé dans une vue. Exécutez-vous le calcul dans la base de données via une seule requête de mise à jour, ou sélectionnez-vous les données dans la base de données, exécutez-vous les calculs dans un autre processus, puis chargez-les à nouveau?
Oracle est configuré par défaut pour utiliser l'exécution en mode instantané, ce qui signifie que les lignes ne sont pas verrouillées pendant la mise à jour et les sélections simultanées obtiennent la valeur d'origine. SQL Server est configuré par défaut avec une concurrence pessimiste, donc les sélections simultanées seront bloquées jusqu'à la fin de la mise à jour. Certaines versions de SQL Server peuvent être mises en mode instantané, mais cela augmente considérablement le stress sur la table temporaire.
Dans quel type d'environnement travaillez-vous? S'il s'agit d'un SGBDR sur une instance EC2 dans Amazon, essayez de placer les fichiers de données DB sur le disque flash local. J'ai vu un ordre de grandeur de différence dans le déplacement des fichiers d'EBS vers le disque local.
la source