La réponse courte ici est "essais et erreurs guidés par des mesures de surveillance et de performances".
Il existe quelques règles générales qui devraient vous aider à trouver la zone vague dans laquelle vous devriez commencer, mais elles sont très générales. Les grandes lignes directrices «nombre de processeurs plus nombre de disques indépendants» sont souvent citées, mais ce n'est qu'un point de départ incroyablement grossier.
Ce que vous devez vraiment faire, c'est mettre en place des mesures de performances robustes pour votre application. Commencez à enregistrer les statistiques.
Il n'y a pas grand-chose en termes d'outils intégrés pour cela. Il y a des choses comme le check_postgres
script nagios , la journalisation du compteur de performances du système Cacti, le collecteur de statistiques PostgreSQL, etc. Malheureusement, vous devrez le faire vous-même. Pour le côté PostgreSQL, voir la surveillance dans le manuel PostgreSQL. Certaines options tierces existent, comme Postgres Enterprise Monitor d'EnterpriseDB .
Pour les mesures au niveau de l'application mentionnées ici, vous souhaiterez les enregistrer dans des structures de données partagées ou dans une base de données externe non durable comme Redis et les agréger soit au fur et à mesure que vous les enregistrez, soit avant de les écrire dans votre base de données PostgreSQL. Essayer de vous connecter directement à Pg faussera vos mesures avec la surcharge créée par l'enregistrement des mesures et aggravera le problème.
L'option la plus simple est probablement un singleton dans chaque serveur d'applications que vous utilisez pour enregistrer les statistiques des applications. Vous voulez probablement garder une mise à jour constante min, max, n, total et moyenne; de cette façon, vous n'avez pas à stocker chaque point de statistique, juste les agrégats. Ce singleton peut écrire ses statistiques agrégées sur Pg toutes les x minutes, un taux suffisamment bas pour que l'impact sur les performances soit minime.
Commencer avec:
Quelle est la latence des requêtes? En d'autres termes, combien de temps l'application prend-elle pour recevoir une demande du client jusqu'à ce qu'elle réponde au client. Enregistrez-les globalement sur une période de temps plutôt que sous forme d'enregistrements individuels. Regroupez-le par type de demande; disons, par page.
Quel est le délai d'accès à la base de données pour chaque requête ou type de requête que l'application exécute? Combien de temps faut-il pour demander à la base de données des informations / stocker des informations jusqu'à ce qu'elles soient terminées et pouvoir passer à la tâche suivante? Encore une fois, agrégez ces statistiques dans l'application et écrivez uniquement les informations agrégées dans la base de données.
Quel est votre débit? En x minutes, combien de requêtes de chaque classe principale exécutée par votre application sont traitées par la base de données?
Pour cette même plage de temps de x minutes, combien de demandes de clients y avait-il?
Échantillonnage toutes les quelques secondes et agrégation sur les mêmes fenêtres de x minutes dans la base de données, combien de connexions à la base de données y avait-il? Combien d'entre eux étaient inactifs? Combien étaient actifs? Dans les encarts? Mises à jour? sélectionne? supprime? Combien de transactions y a-t-il eu durant cette période? Voir la documentation du collecteur de statistiques
Encore une fois, l'échantillonnage et l'agrégation sur le même intervalle de temps, à quoi ressemblaient les mesures de performances du système hôte? Combien lisent et combien écrivent des E / S disque / seconde? Mégaoctets par seconde de lecture et d'écriture sur le disque? Utilisation du processeur? Charge moyenne? Utilisation de la RAM?
Vous pouvez maintenant commencer à vous renseigner sur les performances de votre application en corrélant les données, en les représentant graphiquement, etc. Vous commencerez à voir des modèles, à trouver des goulots d'étranglement.
Vous pouvez apprendre que votre système est limité INSERT
et fonctionne UPDATE
à des taux de transaction élevés, malgré des E / S de disque assez faibles en mégaoctets par seconde. Ce serait un indice dont vous avez besoin pour améliorer vos performances de vidage de disque avec un contrôleur RAID de mise en cache à écriture différée alimenté par batterie ou certains SSD de haute qualité protégés par l'alimentation. Vous pouvez également utiliser synchronous_commit = off
si vous pouvez perdre quelques transactions en cas de panne du serveur et / oucommit_delay
, pour supprimer une partie de la charge de synchronisation.
Lorsque vous représentez vos transactions par seconde par rapport au nombre de connexions simultanées et que vous corrigez le taux de demande variable que l'application voit, vous pourrez avoir une meilleure idée de l'endroit où se situe votre zone de débit idéale.
Si vous n'avez pas de stockage à vidage rapide (BBU RAID ou SSD durables rapides), vous ne voudrez pas plus qu'un nombre assez petit de connexions d'écriture active, peut-être au plus 2x le nombre de disques que vous avez, probablement moins selon l'arrangement RAID , les performances du disque, etc. Dans ce cas, cela ne vaut même pas la peine d'essais et d'erreurs; il suffit de mettre à niveau votre sous-système de stockage vers un avec des vidages de disque rapides .
Voir pg_test_fsync
pour un outil qui vous aidera à déterminer si cela pourrait être un problème pour vous. La plupart des packages PostgreSQL installent cet outil dans le cadre de contrib, vous ne devriez donc pas avoir besoin de le compiler. Si vous obtenez moins de quelques milliers d'opérations / seconde, pg_test_fsync
vous devez d' urgence mettre à niveau votre système de stockage. Mon ordinateur portable équipé d'un SSD obtient de 5000 à 7000. Ma station de travail au travail avec une matrice RAID 10 à 4 disques de disques SATA à 7 200 tr / min et l'écriture directe (sans mise en cache en écriture) obtient environ 80 opérations / seconde f_datasync
, jusqu'à 20 opérations / seconde pour fsync()
; c'est des centaines de fois plus lent . Comparatif: ordinateur portable avec SSD vs station de travail avec RAID 10 à écriture immédiate (sans mise en cache en écriture). Le SSD de cet ordinateur portable est bon marché et je ne lui fais pas nécessairement confiance pour vider son cache d'écriture en cas de coupure de courant; Je garde de bonnes sauvegardes et je ne l'utiliserais pas pour les données qui me tiennent à cœur. Les SSD de bonne qualité fonctionnent aussi bien sinon mieux et sont durables en écriture.
Dans le cas de votre candidature, je vous conseille fortement de vous pencher sur:
- Un bon sous-système de stockage avec des rinçages rapides. Je ne peux insister assez sur ce point. SSD de bonne qualité à sécurité intégrée et / ou contrôleur RAID avec cache de réécriture protégé par alimentation.
- En utilisant
UNLOGGED
tableaux pour les données que vous pouvez vous permettre de perdre. Agrégez-le périodiquement dans des tables enregistrées. Par exemple, gardez les jeux en cours dans des tables non enregistrées et écrivez les scores dans des tables durables ordinaires.
- Utilisant un
commit_delay
(moins utile avec un stockage à vidage rapide - indice)
- Éteindre
synchronous_commit
pour les transactions que vous pouvez vous permettre de perdre (moins utile avec le stockage à vidage rapide - indice)
- Tables de partitionnement, en particulier les tables où les données "vieillissent" et sont nettoyées. Au lieu de supprimer d'une table partitionnée, supprimez une partition.
- Index partiels
- Réduction du nombre d'index que vous créez. Chaque index a un coût d'écriture.
- Travail en lots dans des transactions plus importantes
- Utilisation de réplicas de secours à chaud en lecture seule pour supprimer la charge de lecture de la base de données principale
- Utiliser une couche de mise en cache comme memcached ou redis pour les données qui changent moins souvent ou peuvent se permettre d'être périmées. Vous pouvez utiliser
LISTEN
et NOTIFY
pour effectuer l'invalidation du cache à l'aide de déclencheurs sur les tables PostgreSQL.
En cas de doute: http://www.postgresql.org/support/professional_support/
synchronous_commit = off
ou uncommit_delay
?