A propos des performances des bases de données mono-threadées par rapport aux bases multithreads


58

H2 est une base de données à thread unique avec une bonne réputation en termes de performances. D'autres bases de données sont multi-threadées.

Ma question est la suivante: quand une base de données multithreads devient-elle plus intéressante qu'une base de données à un seul thread? Combien d'utilisateurs? Combien de processus? Quel est le déclencheur? Quelqu'un a de l'expérience à partager?

Sommaire

  • Le goulot d'étranglement habituel est l'accès au disque
  • Les disques SSD sont rapides mais fragiles (une procédure en cas d'échec est indispensable)
  • Une longue requête sur un système à un seul thread bloquera tous les autres
  • Configurer un système multi-threading peut être délicat
  • Les bases de données multithread sont utiles même sur des systèmes à cœur unique

Thread signifie "thread ou processus" aux fins de cette question, autant que je sache - par exemple, postgres n'est pas multi-thread mais la question ne cherche pas à comparer (H2, postgres) avec (Oracle, SQL Server, etc.)
Jack Douglas

Réponses:


31

Voici mon avis:

En général, le goulot d'étranglement (ou la partie la plus lente) d'un système de base de données est le disque. Le processeur ne fait des pics que pendant les opérations arithmétiques, le traitement ou toute autre tâche exécutée par le processeur. Avec une architecture appropriée, le multithreading peut aider à compenser la charge d'une requête sur le CPU au lieu d'effectuer les lectures / écritures de disque lentes. Dans certains cas, il est plus rapide de calculer une valeur à l'aide des cycles de la CPU plutôt que de créer une colonne calculée (précédemment enregistrée sur le disque) et de lire cette colonne à partir du disque.

Dans certains SGBDR, il existe un DB temporaire (tempdb) utilisé par tous les DB de cette instance pour le tri, le hachage, les variables temporaires, etc. Le multithreading et le fractionnement de ces fichiers tempdb peuvent être utilisés pour améliorer le débit de la tempdb. , améliorant ainsi les performances globales du serveur.

En utilisant le multithreading (parallélisme), le jeu de résultats d'une requête peut être fractionné pour être traité sur les différents cœurs du serveur, plutôt que d'utiliser un seul cœur. Cette fonctionnalité n'améliore pas toujours les performances, mais dans certains cas, c'est le cas et par conséquent, elle est disponible.

Les threads disponibles dans la base de données sont utilisés à de nombreuses fins: lecture / écriture sur disque, connexions utilisateur, tâches en arrière-plan, verrouillage / verrouillage, E / S réseau, etc. géré à l'aide d'attentes et de files d'attente. Si le processeur parvient à écraser ces threads assez rapidement, les temps d'attente seront faibles. Une base de données multithread sera plus rapide qu'une base de données mono-thread, car dans une base de données mono-thread, il y aura la surcharge de ne recycler qu'un seul thread au lieu d'avoir d'autres bandes de roulement facilement disponibles.

L’évolutivité devient également un problème, puisqu’il faudra davantage de threads pour gérer et exécuter le système DB mis à l’échelle.


Merci pour la perspicacité. J'entends des gens louer des disques SSD. Je suppose que l’investissement dans ces domaines est probablement la meilleure chose à faire après s’être assuré que les requêtes sont bien écrites et que l’application est raisonnablement mise en parallèle.
Jérôme Verstrynge

@Stan - Je pense que multithreadeddans ce contexte, cela signifie quelque chose de différent , c'est-à-dire que toutes les transactions sont sérialisées comme le mentionne Luke dans sa réponse.
Jack Douglas

@ JVerstry ~ Non, pas vraiment. Allez lire les réflexions de Jeff Atwood sur les SSD… ils ont un taux d'échec élevé. La meilleure chose à faire est d’indexer correctement les données et d’avoir des requêtes bien écrites.
jcolebrand

@jcolebrand Ok, il semble préconiser la vitesse uniquement avec un système de sauvegarde solide en cas d'échec
Jérôme Verstrynge

2
@ Jverstry ~ Oui, et si vous comprenez ce concept et que vous l'acceptez, il vous suffit de reconstruire tout votre environnement de production (ou d'attendre un basculement automatisé pour démarrer puis de le reconstruire ultérieurement). allez-y, ils vont encore accélérer, oui.
jcolebrand

47

S'il y a une chose que je peux dire à propos de MySQL, c'est qu'InnoDB, son moteur de stockage transactionnel (compatible ACID), est effectivement multithread. Cependant, il est aussi multithread que vous le configurez !!! Même immédiatement "prêt à l'emploi", InnoDB fonctionne parfaitement dans un environnement à processeur unique, compte tenu de ses paramètres par défaut. Pour tirer parti des fonctionnalités de multithreading InnoDB, vous devez vous rappeler d'activer de nombreuses options.

innodb_thread_concurrency définit la limite supérieure du nombre de threads simultanés pouvant être maintenus ouverts par InnoDB. Le nombre optimal à définir pour cela est (2 X Nombre de CPU) + Nombre de disques. UPDATE : Comme je l'ai appris personnellement de la conférence Percona NYC, vous devez définir cette valeur sur 0 afin de permettre à InnoDB Storage Engine de rechercher le meilleur nombre de threads pour l'environnement dans lequel il s'exécute.

innodb_concurrency_tickets définit le nombre de threads pouvant contourner la vérification de la concurrence en toute impunité. Une fois cette limite atteinte, la vérification de la concurrence des threads redevient la norme.

innodb_commit_concurrency définit le nombre de transactions simultanées pouvant être validées. Étant donné que la valeur par défaut est 0, le fait de ne pas définir cette option permet à un nombre quelconque de transactions d'être validées simultanément.

innodb_thread_sleep_delay définit le nombre de millisecondes pendant lequel un thread InnoDB peut être en veille avant de revenir à la file d'attente InnoDB. La valeur par défaut est 10000 (10 sec).

innodb_read_io_threads et innodb_write_io_threads (les deux depuis MySQL 5.1.38) allouent le nombre spécifié de threads pour les lectures et les écritures. La valeur par défaut est 4 et la valeur maximale est 64.

innodb_replication_delay impose un délai de traitement sur un esclave si innodb_thread_concurrency est atteint.

innodb_read_ahead_threshold autorise les lectures linéaires du nombre défini d'étendues (64 pages [page = 16K]) avant de passer en lecture asynchrone.

Le temps m'échapperait si je nommais plus d'options. Vous pouvez en savoir plus sur la documentation de MySQL .

La plupart des gens ne sont pas au courant de ces fonctionnalités et sont très satisfaits d'InnoDB, qui vient d'effectuer des transactions conformes à l'ACID. Si vous modifiez l'une de ces options, vous le faites à vos risques et périls.

J'ai joué avec les instances de pool de mémoire tampon multiples MySQL 5.5 (162 Go dans 9 instances de pools de mémoire tampon) et j'ai tenté de partitionner automatiquement les données en mémoire de cette façon. Certains experts estiment que cela devrait vous permettre d’améliorer les performances de 50%. Ce que j'ai obtenu est une tonne de blocage du fil qui a réellement fait ramper InnoDB. Je suis passé à 1 tampon (162 Go) et tout allait bien dans le monde. Je suppose que vous avez besoin d’experts Percona à votre disposition pour régler ce problème. Je serai à la conférence MySQL Percona à New York demain et poserai des questions à ce sujet si l'occasion se présente.

En conclusion, InnoDB se comporte bien maintenant dans un serveur multi-processeurs étant donné ses paramètres par défaut pour les opérations multithread. Les peaufiner demande beaucoup de soin, beaucoup de patience, une bonne documentation et un excellent café (ou Red Bull, Jolt, etc.).

Bonjour, bonsoir et bonne nuit !!!

MISE À JOUR 2011-05-27 20:11

Nous sommes revenus de la conférence MySQL Percona à New York jeudi. Quelle conférence. J'ai beaucoup appris, mais j'ai obtenu une réponse sur InnoDB. Ronald Bradford m'a informé que le réglage de innodb_thread_concurrency à 0 laisserait InnoDB choisir le meilleur plan d'action en interne avec la simultanéité des threads. Je vais expérimenter cela davantage dans MySQL 5.5.

MISE À JOUR 2011-06-01 11:20

En ce qui concerne une longue requête, InnoDB est conforme à ACID et fonctionne très bien avec le contrôle de simultanéité MultiVersion . Les transactions doivent pouvoir supporter des niveaux d'isolation (lectures répétables par défaut) qui empêchent les autres d'accéder aux données.

En ce qui concerne les systèmes multicœurs, InnoDB a parcouru un long chemin. Dans le passé, InnoDB ne pouvait pas fonctionner correctement dans un environnement multicœur. Je me souviens d'avoir dû exécuter plusieurs instances de mysql sur un seul serveur pour que les multiples cœurs distribuent les multiples processus mysqld sur les processeurs. Ce n'est plus nécessaire, grâce à Percona et plus tard à MySQL (Oracle, ce qui me fait encore peur), car ils ont développé InnoDB en un moteur de stockage plus mature qui peut accéder aux cœurs avec une simplicité sans trop de réglage. L'instance actuelle d'InnoDB peut aujourd'hui fonctionner correctement sur un serveur principal unique.


11

Dès que vous avez plusieurs utilisateurs ou processus simultanés, ou même un seul processus avec un accès multi-thread à la base de données, disposer d'une base de données prenant en charge le threading deviendra potentiellement intéressant.

H2 est thread-safe, mais sérialise toutes les requêtes dans la base de données, ce qui peut devenir un problème de performances potentiel dans un scénario de charge lourde. Que ce soit réellement le cas pour un projet particulier dépend de la combinaison de vos exigences de performances, du nombre de threads / utilisateurs / processus accédant à la base de données, de la fréquence des requêtes exécutées par ces threads, ainsi que des performances moyennes et défavorables de vos projets. requêtes.

Par exemple, si vos exigences en matière de performances exigent une réponse dans la seconde, si vous n'exécutez pas plus de 10 utilisateurs simultanés exécutant une requête unique dont l’exécution prend 0,05 seconde, une base de données à thread unique vous autoriserait toujours à atteindre ces objectifs (bien qu’il soit multithread). donnerait probablement déjà un gain de performance notable). Dans le même scénario, avec une requête potentielle unique avec une performance d'une demi-seconde dans le pire des cas, la sérialisation de l'accès à votre base de données ne vous permettra plus d'atteindre vos objectifs de performance.

Si vous utilisez actuellement H2 sur votre projet, je vous conseillerais d'exécuter un profileur sur votre base de code dans un scénario de chargement (lancez simplement un nombre x de threads frappant votre code simultanément à l'aide de cas d'utilisation typiques). Cela vous donnera des mesures réelles concernant les performances et les goulots d'étranglement dans votre base de code, au lieu de simplement théoriser. Si cela montre que vos demandes passent un pourcentage important de leur temps à attendre d'accéder à la base de données, il est temps de passer à une base de données threadée.


H2 sérialise-t-il toutes les demandes - ou simplement le DML?
Jack Douglas

8

D'après ce que je peux dire, "single-threaded" est un abus de langage pour H2. Le fait est qu'il sérialise toutes les transactions (c'est-à-dire les fait une à la fois).

La question cruciale pour savoir si c'est "ok" ou non pour votre application n'est pas "Combien d'utilisateurs?" ou même "Combien de processus?", mais "Combien de temps mes transactions vont-elles prendre?"

Si toutes vos transactions sont inférieures à une seconde, cela peut être correct, si certaines prennent plusieurs heures, cela risque de ne pas être correct car toutes les autres transactions en attente attendent qu'elles se terminent. La décision quant à savoir si cela est "correct" ou non dépendra de vos propres exigences en matière de performances. Par exemple, combien de temps faut-il attendre pour que mes utilisateurs accèdent à la base de données avec des transactions?

--MODIFIER

Il semble que H2 ne sérialise pas vraiment les transactions - juste DML. En d'autres termes, de nombreuses mises à jour courtes au sein d'une transaction longue ne bloquent pas les autres mises à jour . Cependant, sauf si vous utilisez la fonctionnalité expérimentale MVCC , le verrouillage de table signifie que cela a un effet similaire dans la pratique. Il existe également une fonctionnalité expérimentale "multi_threaded" mais elle ne peut pas être utilisée en même temps que MVCC.


5

En citant des fragments du site PostgreSQL ... Veuillez noter que je n’ai absolument aucune idée du bien-fondé de ces arguments - ils ne rentrent tout simplement pas dans un commentaire.

Depuis la FAQ des développeurs ("Pourquoi les threads ne sont pas utilisés ..."):

http://wiki.postgresql.org/wiki/Developer_FAQ#Why_don.27t_you_use_threads.2C_raw_devices.2C_async-I.2FO.2C_.3Cinsert_votre_favorite_wizz-bang_feature_here.3E.3F

Les threads ne sont actuellement pas utilisés à la place de plusieurs processus pour les backends car: (...)

  • Une erreur dans un backend peut corrompre d'autres backends si ce sont des threads au sein d'un seul processus
  • Les améliorations de la vitesse utilisant des threads sont faibles comparées au temps de démarrage restant.
  • Le partage de mappages d'exécutables en lecture seule et l'utilisation de shared_buffers signifie que les processus, tels que les threads, utilisent très efficacement la mémoire.
  • La création et la destruction régulières de processus aident à protéger contre la fragmentation de la mémoire, qui peut être difficile à gérer dans des processus de longue durée

Dans la liste Todo ("Fonctionnalités que nous ne voulons pas"):

http://wiki.postgresql.org/wiki/Todo#Features_We_Do_Not_Want

Tous les moteurs fonctionnant en tant que threads dans un seul processus (non voulu)

Cela élimine la protection des processus que nous obtenons de la configuration actuelle. La création de threads est généralement identique à celle des processus sur les systèmes modernes. Il est donc déconseillé d'utiliser un modèle purement threadé. MySQL et DB2 ont démontré que les threads introduisaient autant de problèmes qu'ils résolvaient. (...)

Donc, encore une fois ... je n'ai absolument aucune idée des mérites de ce qui précède. C'était simplement trop long pour tenir dans un commentaire.


-3

Une base de données multithread ne vous sera utile que si vous avez plus d'une requête parallèle envoyée à la base de données. Cela dépend du nombre d'utilisateurs que vous avez. Si vous avez plus de dix utilisateurs travaillant sur l'application en même temps, il est probable qu'ils vont générer plus d'une requête sur la base de données en même temps.

De plus, une base de données multithread ne peut en bénéficier que s'il existe plusieurs cœurs sur le processeur. S'il existe un seul cœur, la base de données multithreads doit mettre le travail en file d'attente et les exécuter de manière séquentielle sur le cœur unique. Lorsqu'il y a plusieurs cœurs, chaque cœur peut exécuter un thread en parallèle. Donc de meilleures performances.

Est-ce que cela répond à votre requête?


7
Les bases de données multithread sont bénéfiques même sur des systèmes à cœur unique. Cela empêche une requête longue et longue de bloquer tous les autres accès à la base de données. De plus, plusieurs threads peuvent être en attente sur le disque ou les E / S réseau, tandis qu'un autre thread analyse activement les requêtes, traite les données déjà extraites, etc.

Un utilisateur peut utiliser un programme qui parallèle certaines opérations. Ce programme aurait probablement des avantages si la base de données avait également des capacités multi-threading / multi-processing
joanolo
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.