La respuesta breve aquí es "ensayo y error guiados por métricas de monitoreo y rendimiento".
Existen algunas reglas generales que deberían ayudarlo a encontrar el área vaga en la que debería comenzar, pero son muy generales. A menudo se citan las pautas generales "número de CPU más número de discos independientes", pero es solo un punto de partida increíblemente tosco.
Lo que realmente necesita hacer es obtener métricas de rendimiento sólidas para su aplicación. Comience a registrar estadísticas.
No hay mucho en el camino de herramientas integradas para esto. Hay cosas como el check_postgres
script nagios , el registro del contador de rendimiento del sistema Cacti, el recopilador de estadísticas PostgreSQL, etc., pero no hay mucho que lo reúna todo. Lamentablemente, tendrás que hacer eso mismo. Para el lado de PostgreSQL, vea monitoreo en el manual de PostgreSQL. Existen algunas opciones de terceros, como Postgres Enterprise Monitor de EnterpriseDB .
Para las métricas de nivel de aplicación mencionadas aquí, querrá registrarlas en estructuras de datos compartidas o en una base de datos externa no duradera como Redis y agregarlas a medida que las registra o antes de escribirlas en su base de datos PostgreSQL. Intentar iniciar sesión directamente en Pg distorsionará sus mediciones con la sobrecarga creada al registrar las mediciones y empeorará el problema.
La opción más simple es probablemente un singleton en cada servidor de aplicaciones que use para registrar las estadísticas de la aplicación. Probablemente desee mantener una actualización constante min, max, n, total y media; de esa manera no tiene que almacenar cada punto de estadística, solo los agregados. Este singleton puede escribir sus estadísticas agregadas en Pg cada x minutos, una tasa lo suficientemente baja como para que el impacto en el rendimiento sea mínimo.
Empezar con:
¿Cuál es la latencia de solicitud? En otras palabras, cuánto tiempo tarda la aplicación en recibir una solicitud del cliente hasta que responde al cliente. Registre esto en conjunto durante un período de tiempo, en lugar de como registros individuales. Agrúpelo por tipo de solicitud; digamos, por página.
¿Cuál es el retraso de acceso a la base de datos para cada consulta o tipo de consulta que ejecuta la aplicación? ¿Cuánto tiempo lleva pedirle a la base de datos información / almacenar información hasta que esté lista y pueda pasar a la siguiente tarea? Nuevamente, agregue estas estadísticas en la aplicación y solo escriba la información agregada en la base de datos.
¿Cómo es tu rendimiento? En cualquier x minutos, ¿cuántas consultas de cada clase principal que ejecuta su aplicación reciben servicio de la base de datos?
Para ese mismo rango de tiempo de x minutos, ¿cuántas solicitudes de clientes hubo?
Tomando muestras cada pocos segundos y agregando sobre las mismas ventanas de x minutos en la base de datos, ¿cuántas conexiones de base de datos había? ¿Cuántos de ellos estaban ociosos? ¿Cuántos estaban activos? En insertos? Actualizaciones? selecciona? elimina? ¿Cuántas transacciones hubo durante ese período? Ver la documentación del recopilador de estadísticas
Nuevamente muestreando y agregando durante el mismo intervalo de tiempo, ¿cómo eran las métricas de rendimiento del sistema host? ¿Cuántas E / S de lectura y disco de escritura / segundo? ¿Megabytes por segundo de disco lee y escribe? ¿Utilización de la CPU? ¿Promedio de carga? Uso de RAM?
Ahora puede comenzar a aprender sobre el rendimiento de su aplicación correlacionando los datos, graficando, etc. Comenzará a ver patrones, comenzará a encontrar cuellos de botella.
Es posible que se entere de que su sistema tiene un cuello de botella INSERT
y UPDATE
está a altas tasas de transacción, a pesar de las E / S de disco bastante bajas en megabytes por segundo. Este sería un indicio de que necesita mejorar el rendimiento del vaciado de disco con un controlador RAID de almacenamiento en caché de escritura de respaldo con batería o algunos SSD de alta calidad con protección de energía. También podría usar synchronous_commit = off
si está bien perder algunas transacciones en caso de bloqueo del servidor, y / o a commit_delay
, para quitar parte de la carga de sincronización.
Cuando grafica tus transacciones por segundo contra el número de conexiones concurrentes y corrige la tasa de solicitud variable que está viendo la aplicación, podrás tener una mejor idea de dónde está tu punto óptimo de rendimiento.
Si no tiene almacenamiento de descarga rápida (BBU RAID o SSD rápidos y duraderos), no querrá más que un número bastante pequeño de conexiones de escritura activa, tal vez como máximo el doble de la cantidad de discos que tiene, probablemente menos dependiendo de la disposición de RAID , rendimiento del disco, etc. En este caso ni siquiera vale la pena probarlo y equivocarlo; simplemente actualice su subsistema de almacenamiento a uno con descargas rápidas de disco .
Busque pg_test_fsync
una herramienta que lo ayudará a determinar si esto podría ser un problema para usted. La mayoría de los paquetes de PostgreSQL instalan esta herramienta como parte de contrib, por lo que no debería necesitar compilarla. Si obtiene menos de un par de miles de operaciones / segundo pg_test_fsync
, necesita actualizar urgentemente su sistema de almacenamiento. Mi portátil equipado con SSD obtiene 5000-7000. Mi estación de trabajo en el trabajo con una matriz RAID 10 de 4 discos de discos SATA de 7200 rpm y escritura a través (almacenamiento en caché sin escritura) obtiene aproximadamente 80 operaciones / segundo f_datasync
, hasta 20 operaciones / segundo para fsync()
; Es cientos de veces más lento . Compare: computadora portátil con SSD vs estación de trabajo con escritura (no-caché de escritura) RAID 10. El SSD de este portátil es barato y no confío necesariamente en que vacie su caché de escritura en caso de pérdida de energía; Mantengo buenas copias de seguridad y no las usaría para los datos que me interesan. Los SSD de buena calidad funcionan igual de bien, si no mejor, y son durables para escritura.
En el caso de su solicitud, le recomiendo encarecidamente que investigue:
- Un buen subsistema de almacenamiento con descargas rápidas. No puedo enfatizar esto lo suficiente. SSD de buena calidad a prueba de fallas de energía y / o un controlador RAID con memoria caché de escritura protegida.
- Usando
UNLOGGED
tablas para datos que puede permitirse perder. Agregue periódicamente en tablas registradas. Por ejemplo, mantenga los juegos en progreso en tablas no registradas y escriba los puntajes en tablas duraderas comunes.
- Usar un
commit_delay
(menos útil con almacenamiento de descarga rápida - pista)
- Desactivar las
synchronous_commit
transacciones que puede permitirse perder (menos útil con el almacenamiento de descarga rápida: pista)
- Tablas de partición, especialmente tablas donde los datos "caducan" y se limpian. En lugar de eliminar de una tabla particionada, suelte una partición.
- Índices parciales
- Reduciendo la cantidad de índices que crea. Cada índice tiene un costo de escritura.
- Lote de trabajo en transacciones más grandes
- Uso de réplicas en espera activa de solo lectura para quitar la carga de lectura de la base de datos principal
- Usar una capa de almacenamiento en caché como memcached o redis para datos que cambian con menos frecuencia o que pueden permitirse ser obsoletos. Puede usar
LISTEN
y NOTIFY
realizar la invalidación de caché utilizando desencadenadores en tablas PostgreSQL.
En caso de duda: http://www.postgresql.org/support/professional_support/
synchronous_commit = off
o acommit_delay
?