Sacarle El Jugo a PostgreSQL

18
2013 Microsoft Josué Vinicio Alemán Watters Algunos consejos generales para aumentar el [ rendimiento en PostgreSQL] Tres importantes investigaciones acerca de cómo sacarle el jugo a este manejador de BD.

Transcript of Sacarle El Jugo a PostgreSQL

Page 1: Sacarle El Jugo a PostgreSQL

2013

Microsoft Josué Vinicio Alemán Watters

Algunos consejos generales para aumentar el [rendimiento en PostgreSQL ]Tres importantes investigaciones acerca de cómo sacarle el jugo a este manejador de BD.

Page 2: Sacarle El Jugo a PostgreSQL

Primera Investigación

Tuning al rendimiento de PostgreSQL Publicado el 9 septiembre, 2011 por wiccano Publicado en Sin categoría 2 respuestas

Antes en entrar en el tema me parece importante aclarar el término anglosajón Tuning con el

que nos referimos a ―puesta a punto‖ de algo.

PostgreSQL es actualmente la Base de Datos SQL de código abierto más avanzada y flexible.

Con este poder y flexibilidad enfrentamos un problema: los desarrolladores de PostgreSQL

suelen ajustar la configuración de modo general, lamentablemente esto no se debe hacer. Esto

se hace para asegurar que el servidor arrancará casi con cualquier configuración hardware.

El punto esta en que cada base de datos no solo es diferente en su diseño sino también en sus

necesidades. Algunas por ejemplo, se usan para recopilar grandes cantidades de datos que casi

nunca son consultados y otras en cambio tienen datos estáticos y que son consultados

frecuentemente. Sin embargo la mayoría de sistemas tienen niveles de escritura y lectura sobre

la base de datos, generalmente desiguales. Sumando a esto la estructura total de la base de

datos, sus tipos de datos y configuración de hardware hacen que hacer tuning al rendimiento de

PostgreSQL no sea una tarea fácil.

Sitios de Referencia:

http://wiki.postgresql.org/wiki/Tuning_Your_PostgreSQL_Server

Entendiendo el proceso

El primer paso para entender como funciona una base de datos PostgreSQL es entender el ciclo

de vida de una consulta. Estos son los pasos que sigue una consulta:

1. Transmisión de la cadena de consulta al backend de la base de datos

2. Análisis(Parsing) de la cadena de consulta

3. Planificación de la consulta para optimizar la recuperación de datos

4. Recuperación de datos desde el hardware

5. Transmisión de los resultados del cliente

El primer paso es el envío de la cadena de consulta (el comando SQL que se tipea desde la

aplicación que se este usando) a la base de datos. No hay mucho que usted pueda ajustar en este

punto. Sin embargo si usted tiene consultas muy grandes o largas que no se construyen de

forma avanzada puede optar por ponerlas en la base de datos como procedimientos

Page 3: Sacarle El Jugo a PostgreSQL

almacenados y así cortar la transferencia de datos a un mínimo que vendría siendo el llamado al

procedimiento almacenado.

Una vez que la consulta SQL esta dentro del servidor de base de datos es analizada(Parsed).

Este paso también puede evitarse con algunas consultas creando procedimientos almacenados.

En la planificación de la consulta es donde PostgreSQL realmente comienza a hacer algún

trabajo. Esta etapa de controles verifican si la consulta ya esta preparada, si la versión de

PostgreSQL y librerias cliente soportan esta característica, función o consulta. Se analiza

también el SQL para determinar cual es la forma más eficiente para recuperar los datos. Se

podría usar un Index, si es así cual debe ser?. Quizás un hashjoin en las dos tablas es lo

adecuado?. Estas son algunas de las decisiones que la base de datos toma en este punto del

proceso. Este paso puede ser eliminado si la consulta es previamente preparada.

Ahora que PostgreSQL tiene un plan de lo que cree, es la mejor manera de recuperar los datos,

es hora de hacerlo realidad. Si bien hay algunas opciones de optimización en este punto del

proceso, la mayoría de son realizadas por la configuración de hardware.

Y finalmente el último paso es transmitir los resultados al cliente. Si bien no hay opciones de

optimización real en este paso es importante tener en cuenta que todos los datos que se van a

devolver son tomados desde el disco y son enviados a través de los medios de conexión al

cliente. Minimizar el número de filas y columnas a solo aquellas que son necesarias a menudo

puede incrementar el rendimiento.

Cuando inicializamos la base de datos PostgreSQL define unos valores por defecto, estos

valores son muy bajos teniendo en cuenta el hardware moderno y de entrada es lo primero que

se debe revisar en el momento de realizar Tuning al rendimiento del motor. La estratégia de

como se debe realizar depende de la magnitud y complejidad la o las bases de datos.

La información de Hardware es lo primero que debe obtener y así saber con que recursos

disponemos. Luego revisamos que tipo de sistemas tenemos, que predomina, la consulta? la

escritura?, existen procesos complejos de procesamiento? que recursos va a utilizar Apache y

PHP y cuales PostgreSQL?, que cantidad de conexiones se producen simultaneamente, etc…

Esta información obetenida sumada a la configuración actual de la máquina y a los resultados

de desempeño que actualmente se tienen de la base de datos y del sistema en general nos da un

punto de partida para realizar el tuning al rendimiento de postgresql. Tomando las medidas de

contingecia respectivas, todo es un juego de tire y afloje. Aumente los valores de configuración

o disminuyalos, inclusive llegando a degradar el sistema y así fijar los limites de rendimiento

que podemos llegar a tener. A continuación describo las principales opciones de configuración

Page 4: Sacarle El Jugo a PostgreSQL

de PostgreSQL que unas ves comprendidas permiten realizar movimientos lógicos de

configuración en buscan de configuraciones acertadas para un sistema en particular.

Archivo de Configuración postgresql.conf

Siempre que realice cambios sobre este archivo debe reiniciar PostgreSQL

En otro capitulo se describen detalladamente las principales opciones de este archivo de

configuración. Por ahora nos vamos a centrar en 3 parametros de configuración

El número de shared_buffers es el parámetro que más afecta al rendimiento de PostgreSQL.

Este valor, de tipo entero, indica el número de bloques de memoria o buffers de 8KB (8192

bytes) que postgres reservará, como zona de trabajo, en el momento del arranque para procesar

las consultas. De forma predeterminada (enpostgresql.conf), su valor es de 1000. Un número

claramente insuficiente para conseguir un rendimiento mínimamente aceptable.

Estos buffers se ubican dentro de los denominados segmentos de memoria compartida. Es

importante saber que el espacio ocupado por el número de buffers que pretendamos asignar,

nunca podrá exceder al tamaño máximo que tengan los segmentos de memoria. En caso

contrario, postgres se negará a arrancar avisando con un error que no puede reservar el espacio

solicitado.

Ahora de forma práctica, vamos a suponer que tenemos un server con 8GB en RAM y vamos a

iniciar dejando 3GB como espacio reservado para postgres.

8GB = 8256992 (esta equivalencia solo la tomo de los datos reportados por el OS)

4GB = 8256992 / 2 = 4128496K

shared_buffers: (4128496 KB/8 KB) = 516062

Es posible que al fijar este valor a shared_buffers en el archivo postgresql.con

f nos genere un error de este tipo

FATAL: no se pudo crear el segmento de memoria compartida: Argumento inválido

DETALLE: La llamada a sistema fallida fue shmget(key=5432001, size=112009216,

03600).

HINT: Este error generalmente significa que una petición de PostgreSQL para

Page 5: Sacarle El Jugo a PostgreSQL

obtener un segmento de memoria compartida excedió el parámetro SHMMAX del

kernel. Puede reducir el tamaño de la petición o reconfigurar el kernel con

un SHMMAX superior. Para reducir el tamaño de la petición (actualmente

112009216 bytes), reduzca el parámetro de PostgreSQL shared_buffers

(actualmente 13107) y/o el parámetro max_connections (actualmente 100).

Si el tamaño de la petición ya es pequeño, es posible que sea inferior

al parámetro SHMMIN del kernel, en cuyo caso se requiere alzar el

tamaño de la petición o disminuir SHMMIN.

La documentación de PostgreSQL contiene más información acerca

de la configuración de memoria compartida.

Nota: recuerda que este valor no debe ser fijado como formula, sino que puede se

r un punto de partida. Recuerda que muchas veces hay que fijar valores tan altos

(con conocimiento de causa claro esta) que hagan que el sistema no funcione más,

así encontrarás los límites de tú configuración.

El tamaño ocupado por los 516062 buffers que has pedido reservar, simplemente no caben en el

tamaño actual de segmento (SHMMAX). Postgres en el arranque intenta reservar este espacio

pero el sistema operativo no se lo permite.

En Linux, de forma predeterminada, el tamaño de un segmento de memoria compartida es de

32MB. Podemos comprobarlo haciendo (el resultado es en nº de bytes):

shell> cat /proc/sys/kernel/shmmax

33554432

Y el espacio que requiere el número de buffers, es superior al tamaño del segmento:

516062 buffers ocupan 4227579904 (516062 * 8192 bytes/bloque) > 33554432

La solución está en modificar el tamaño máximo del segmento de memoria compartid

a. Esto lo hacemos asignando un nuevo valor al parámetro del kernel SHMMAX

shell> sysctl -w kernel.shmmax=4227579904

Ahora, para fijar shmall debes ver como lo fija el mismo OS al momento de cargar, esto lo

puedes ver en /usr/include/linux/shm.h. Encontrarás algo como esto:

Page 6: Sacarle El Jugo a PostgreSQL

#define SHMMAX 0×2000000 /* max shared seg size (bytes) */

#define SHMMIN 1 /* min shared seg size (bytes) */

#define SHMMNI 4096 /* max num of segs system wide */

#define SHMALL (SHMMAX/getpagesize()*(SHMMNI/16))

#define SHMSEG SHMMNI /* max shared segs per process */

Luego podemos decir que:

shmall = 4227579904 / 4096 * (4096 / 16) = 264223744 // estamos hablando de cerca de

260MB frente a los 4GB de shmmax

shell> sysctl -w kernel.shmall=264223744

Ahora debes guardar este valor de forma permanente en /etc/sysctl.conf, de forma que los

cambios se conserven entre arranques:

kernel.shmmax=4227579904

kernel.shmall=264223744

Podemos confirmar de esta forma, aunque en este punto los valores ya deben estar cargados.

sysctl -p /etc/sysctl.conf

Si necesitas más detalles de la configuración de los parametros del kernel puedes revisar

la documentación oficial aquí

######################################################################

La primer sección de este archivo es FILE LOCATIONS, es fácil de interpretar, no voy a entrar

en detalles.

La segunda sección es CONNECTIONS AND AUTHENTICATION. Esta sección de

conexiones se encuentra subdividida en 4 partes: tipo de conexiones, parámetros de

autenticación, kerberos y TCP.

En su configuración inicial, Postgres solo puede ser accedido desde socket unix, sin puertos

TCP/IP abiertos.

Conexiones

listen_addresses = ‘localhost’ — Listado separado por comas de los host desde los cuales se

aceptarán conexiones. De estar comentado ocon valor ‗*‘, acepta desde cualquier host.

port = 5432 – Puerto en el cual esta escuchando esta instancia de Postgres. Notar que con esta

directiva se puedenejecutar múltiples instancias del DBMS.

Page 7: Sacarle El Jugo a PostgreSQL

max_connections = 100 – Cantidad máxima de conexiones permitidas(backends) en un mismo

tiempo, sin considerar al superusuario. Aumentar este parámetro conlleva un mayor uso de

memoria compartida. Al cambiar este parámetro tenga en cuenta que otros parámetros como

work_men se configura con relación a cada cliente.

superuser_reserved_connections = 2 – Cantidad de slots de conexión reservados para el

superusuario

unix_socket_directory = ‘/var/run/postgresql’ – Directorio de los sockets unix para esta

instancia de Postgres. Note que con esta directiva se pueden ejecutar múltiples instancias del

DBMS.

unix_socket_group = ” – Indica el grupo dueño de los sockets unix.

unix_socket_permissions = 0777 – Indica los permisos en octal de acceso a los sockets unix

bonjour_name = ” – Permite establecer el nombre del DBMS. De estar comentado o en

blanco, toma el nombre el equipo host

Seguridad y Autenticación

#authentication_timeout = 60 # 1-600, in seconds. Tiempo en segundos de espera por la

información de login. Desde 1 a 600.

#ssl = true – Indica si el uso de SSL es forzado. De estar comentado es falso.

#password_encryption = on – Flag que indica si el uso de encriptación en el envío de la

contraseña es obligatorio o no. De estarcomentado es apagado.

#db_user_namespace = off – Habilita la funcionalidad donde los nombres de usuario pueden

ser específicos de cada base de datos, es decir, usuario@baseEjemplo quiere decir que usuario

solo se aplicaría a ‗baseEjemplo‘ y no a todas como es por defecto.

Uso de Recursos

En esta sección se puede especificar la cantidad de recursos que esta instancia de PostgreSQL

estaautorizada a consumir.

shared_buffers = 1000 – Editando esta opción es la forma más sencilla de mejorar el

rendimiento del servidor de base de datos. El valor por defecto es muy bajo para la mayoría de

hardware moderno. Generalmente se dice que debería estar en alrededor del 25% de la memoria

RAM disponible en el sistema. En sistemas que tengan menos de 1GB en RAM la proporción

suele ser 15%, dependiendo de la memoria que consume el sistema operativo. En algunas

circunstancias se podrìa requerir màs del 25% pero dado que postgres tambièn utiliza la

memoria compartida del sistema de operativo los valores tan altos no tienen gran relevancia

Page 8: Sacarle El Jugo a PostgreSQL

frente a los valores bajos. Tenga en cuenta que para sistemas abajo de la versión 8.1 los valores

altos en shared_buffers no funcionan bien, en cambio se pueden tener valores de 32MB a cerca

de 400MB funcionando correctamente.

Como la mayoría de las opciones que se resumen aquí, simplemente tendrá que probar

diferentes valores, hacia arriba y hacía abajo, y ver que tan bien funciona el sistema. Muchas

personas van fijando valores altos hasta encontrar el valor que degrada el sistema y así ir

encontrando el ideal.

temp_buffers = 1000 – Los buffers temporales hacen referencia a la cantidad de memoria

utilizada por cada sesión de base de datos para acceder a tablas temporales.

#max_prepared_transactions = 5 – Se recomienda dejar por defecto.5

work_mem = 1024 – Este valor se debe fijar con relación al parámetro max_connections, si

por ejemplo tiene 400 conexiones simultaneas y fija work_mem en 20MB estará utilizando

8GB de memoria compartida. Tenga en cuenta esta medida y fije el valor suficiente ya que este

le permite mejorar el rendimiento de consultas de ordenamiento complejo. Por ejmeplo.

maintenance_work_mem = 16384 – Esta directiva en kilobytes, indica la cantidad de memoria

a utilizar por las labores de mantención como VACUUM, CREATE INDEX, restauración de

bases de datos, etc. Como no se suelen dar operaciones concurrentes de este tipo dejarlo en un

valor como 256MB esta bien.

max_fsm_pages = 20000 – Esta opción ayuda a controlar el Mapeo de Espacio Libre (free

space map(FSM)). Cuando algo es eliminado de la tabla no es removido del disco

inmediatamente. El espacio es realmente marcado como libre en el FSM. El espacio puede ser

reutilizado para cualquier nuevo INSERT realizado en la tabla. Si el sistema tiene una alta tasa

de INSERT y DELETE puede ser necesario aumentar este valor para evitar que las tablas

aumenten desmesuradamente su tamaño.

max_fsm_relations = 1000 – Cantidad de relaciones (tablas e índices) de las cuales se

mantiene monitoreo del espacio libre en el mapade espacio libre. Deben ser al menos 100

Ajustes a las Consultas (Query Tuning)

Configuración de las funciones del planificador. Desabilite la función que necesite pasando a

off

#enable_bitmapscan = on

#enable_hashagg = on

Page 9: Sacarle El Jugo a PostgreSQL

#enable_hashjoin = on

#enable_indexscan = on

#enable_mergejoin = on

#enable_nestloop = on

#enable_seqscan = on

#enable_sort = on

#enable_tidscan = on

Costos del planificador

#effective_cache_size = 16000MB – Este valor le dice al optimizador de PostgreSQL, cuanta

memoria tiene asignada PostgreSQL para el almacenamiento de cache de datos y ayuda en el

momento de la determinación de si crear o no un indice. Cuanto mayor sea el valor se

incrementa la probabilidad de usar un indice. Asigne la cantidad de memoria que queda luego

de determinar la cantidad de memoria que se toma el sistema operativo y las demás

aplicaciones que puedan existir(apache, PHP, etc…). Esta memoria no es que este asignada

realmente sino que es un valor que utiliza el planificador de PostgreSQL para saber si los

planes que están considerando caben en RAM. Establezcalo al 50% de la RAM y aún esto es

algo conservador. Un 75% se podría tener.

#random_page_cost = 4 – Controla la forma en que PostgreSQL ve las lecturas de disco no

secuenciales. Un valor alto hace que sea más probable que una búsqueda secuencial pueda ser

realizada bajo una búsqueda de indices, indicando que el servidor tiene discos muy rápidos.

#cpu_tuple_cost = 0.01 – Costo de procesar una fila en una consulta. El valor esta indicado en

una fracción del costo de recuperación de una página secuencial.

#cpu_index_tuple_cost = 0.001 – Costo de proceso de una fila durante un escaneo vía índice.

El valor esta indicado en una fracción del costo de recuperación de una página secuencial.

#cpu_operator_cost = 0.0025 - Costo estimado de procesar cada operador en una cláusula

WHERE. El valor está indicado en una fracción del costo de recuperación de una página

secuencial.

Optimizador Genético de Consulta (GEQO Genetic Query Optimizer)

PostgreSQL incorpora dentro de su analizador de consultas, un algoritmo genético para

optimización de consultas que incorporan JOIN. Las siguientes directrices permiten ajustar el

comportamiento de este algoritmo.

Page 10: Sacarle El Jugo a PostgreSQL

Los algoritmos genéticos son una optimización heurística que opera de forma no-

determinística. El set desoluciones posibles para el problema se denomina población, mientras

que el grado de adaptación de un individuo se llama ajuste. Las coordenadas del individuo

dentro del espacio de soluciones se representa por cromosomas. Un gene es una subsección de

un cromosoma el cual codifica el valor de un único parámetrodentro de la optimización.

Para obtener la solución se simula la recombinación y mutación de los individuos, realizándose

la selección natural en base a aquel individuo que presenta en promedio un mayor grado de

adaptación que sus ancestros.

#geqo = on – Habilita o deshabilita el uso del algorítmo genético.

#geqo_threshold = 12 – Cantidad de elementos en la cláusula FROM desde los cuales el

algorítmo genético es utilizado.

#geqo_effort 0 5 – Controla en enteros de 1 a 10, la proporción de tiempo que el planificador

gasta en planificar y la efectivdad del mismo. Valores más altos resultarán en un tiempo mayor

de planificación, pero también aumenta la probabilidad de encontrar un plan más eficiente.

#geqo_pool_size = 0 – Cantidad de individuos en la población, debiendo haber al menos 2. De

fijarse en 0 se elige un tamaño óptimo con base al esfuerzo indicado en geqo_effort

#geqo_generations = 0 – Controla la cantidad de generaciones(iteraciones) usadas por GEQO.

Debe ser al menos 1. Fijando en 0 hace que el motor escoja un valor adecuado con base al

esfuerzo indicado en geqo_effort.

#geqo_selection_bias = 2.0 – Ajusta la presión de selección dentro de la población, valor de

1.5 a 2.0.

#default_statistics_target = 10 – Indica la cantidad de columnas a usar en el análisis, en

consultas que no se especifica o no se ha indicado vía ALTER TABLE SER STATISTICS.

#constraint_exclusion = off – Al estar habilitado compara las condiciones de la consulta con

las restricciones de la tabla impuestas en CHECK.

#from _collapse_limit = 8 – El planificador juntará subconsultas hacia niveles superiores si la

lista resultante en la cláusula FROM notiene más elementos que este valor. Valores pequeños

resultan en planificaciones más cortas, pero menosefectivas. Es conveniente dejar este valor

bajo gego_threshold.

#join_collapse_limit = 8 – El planificador rescribirá los INNER JOINs de la consulta a items

FROM, siempre y cuando el largo de la listaen esa cláusula no sobrepase este valor. No tiene

Page 11: Sacarle El Jugo a PostgreSQL

efecto alguno en OUTTER JOINs. Fijar su valor a 1, inhibe la reescritura haciendo el

planificador se comporte como la versión 7.3

parámetros de Autovacuum

A partir de la versión 8.1 de PostgreSQL, existe un subproceso separado llamado demonio

autovacuum. Este es el encargado de revisar periódicamente la tablas con modificación

considerables a su tuplas. Los datos utilizados por el demonio son aquellos generados al

estar stats_start_collector y stats_row_levelencendidos. El proceso se conecta a la base de

datos utilizando alguno de los slots de superusuario reservados.

El subproceso realiza 2 tareas: VACUUM y ANALYZE sobre las tablas que hayan alcanzado

el nivel de cambio indicado

por autovacuum_vacuum_threshold y autovacuum_analyze_threshold respectivamente.

autovacuum = on – Indica si ejecutar el proceso autovacuum o no

#autovacuum_naptime = 1 min – Tiempo que duerme el proceso de autovacuum entre

ejecuciones

#autovacuum_vacuum_threshold = 500 — Umbral para determinar cuando se aplica

VACUUM a una tabla. Cuando el valor calculado de la base más la cantidad de filas

modificadas multiplicadas por el factor supera este valor, entonces se ejecuta VACUUM sobre

la tabla.

#autovacuum_analyze_threshold = 250 – Umbral para determinar cuando se aplica

ANALYZE a una tabla. Cuando el valor calculado de la base más la cantidad de filas

modificadas multiplicadas por el factor supera este valor, entonces se ejecuta ANALYZE sobre

la tabla.

#autovacuum_vacuum_scale_factor = 0.2 – Factor por el cual se multiplican la cantidad de

filas modificadas de una tabla para obtener el umbral de ejecución de vacuum sobre esta tabla.

#autovacuum_analyze_scale_factor = 0.1 – Factor por el cual se multiplican la cantidad de

filas modificadas de una tabla para obtener el umbral de ejecución de analyze sobre esta tabla.

Estas son las principales opciones de configuración de PostgreSQL que impactan notoriamente

el rendimiento de la base de datos. Evalue y ajuste hasta que encuentre la configuración de

mayor rendimiento para sus necesidades.

Cuestiones de Hardware

Page 12: Sacarle El Jugo a PostgreSQL

Obviamente el tipo y la calidad de Hardware que se usa impacta drasticamente el rendimiento

de la base de datos. Estos son algunos consejos a la hora de comprar hardware para su servidor

de base de datos, en orden de importancia:

RAM — Entre más RAM se tenga debe tener más cache de disco. Esto afecta en gran medida el

rendimiento teniendo en cuenta que la memoria de E / S es miles de veces más rápida que la E / S

del disco.

Disk types — Definitivamente los rápidos discos SCSI Ultra-320 son la mejor opción. Sin embargo

los discos SATA de alta gama también son muy buenas. Los discos SATA son mucho más

económicos y con ellos se pueden tener muchos más ejes en su estructura de almacenamiento por

el mismo precio.

Disk configuration — La confuguración más óptima es RAID 1+0 con tantos discos como sea posible

y con le registro de transacciones (pg_xlog) en un disco independiente, bien sea físico o

viertual(Stripe Disk). RAID 5 no es una opción recomendada a no ser que tenga más de 6 discos en

su volumen. Con las nuevas versiones de PostgreSQL se puede utilizar la opción de tablespace para

poner tablas, base de datos e indices en discos diferentes para mejorar el dendimiento. Así como

poner las tablas de uso frecuente en un disco SCSI y las menos utilizadas en discos más lentos SATA

o IDE.

CPUs — Entre mejor CPU se tenga mejor rendimiento, sin embargo, si su base de datos no utiliza

muchas funciones complejas es mejor invertir el dinero en más memoria RAM o un mejor sistema

de discos.

En general cuanto más RAM se tenga y más posibilidad de conexiones de disco el sistema

funcionará mejor. Esto por que entre más RAM exista menos acceso al disco se realiza y entre

más conexiones de disco existan disponibles es posible distribuir las operaciones de lectura y

escritura en disco, aumentando el rendimiento y disminuyendo los cuellos de botella.

Otra buena idea es separar el código de la aplicación de la base de datos en diferente hardware.

Esto significa que no solo se va a tener más hardware disponible para la base de datos sino que

la memoria cache del sistema operativo contendrá más datos PostgreSQL y no de otro tipo de

aplicaciones o procesos.

Por ejemplo, si usted tiene un servidor web y un servidor de base de datos se puede usar un

cable cruzado por interfaces de redes exclusivas para que estos dos se comuniquen y a su vez el

servidor web utiliza otra conexión diferente para comunicarse con sus clientes. Si son varios

servidores web accediendo a un mismo servidor de base de datos podría armar una red

independiente y esclusiva para este tráfico.

Una vez tengamos la mejor configuración es ideal revisar todo tipo de consultas que recibe la

base de datos y ver en que medida se puede mejorar su rendimiento. Para iniciar debe ubicar las

Page 13: Sacarle El Jugo a PostgreSQL

consultas más repetitivas y las que más consumen tiempo de ejecución. En otro articulo puede

encontrar más información de como ubicar este tipo de consultas.

Herramientas Útiles para realizar Tuning a las Consultas

La herrmienta más usada para realizar Tuning a la base de datos es el comando SQL EXPLAIN

ANALYZE. Este permite ver el registro de cada consulta SQL que es llevada a cabo y ver

exactamente como el planificador de PostgreSQL procesa cada consulta. Veamos este ejemplo:

CREATE TABLE authors (

id int4 PRIMARY KEY,

name varchar

);

CREATE TABLE books (

id int4 PRIMARY KEY,

author_id int4,

title varchar

);

Si usamos la consulta

EXPLAIN ANALYZE SELECT authors.name, books.title

FROM books, authors

WHERE books.author_id=16 and authors.id = books.author_id

ORDER BY books.title;

Se obtiene una salida como esta

QUERY PLAN ------------------------------------------------------------------------------

---------------------------------------------- Sort (cost=29.71..29.73 rows=6 width=64) (

actual time=0.189..16.233 rows=7 loops=1) Sort Key: books.title -> Nested Loop (cost=0.00

..29.63 rows=6 width=64) (actual time=0.068..0.129 rows=7 loops=1) -> Index Scan using au

thors_pkey on authors (cost=0.00..5.82 rows=1 width=36) (actual time=0.029..0.033 rows=1

loops=1) Index Cond: (id = 16) -> Seq Scan on books (cost=0.00..23.75 rows=6 width=36) (a

ctual time=0.026..0.052 rows=7 loops=1) Filter: (author_id = 16) Total runtime: 16.386 ms

La salida se debe analizar de abajo hacia arriba. Lo primero que hace PostgreSQL es una

búsqueda secuencial sobre la tabla books ubicando la colúmna author_id con un valor igual a

16. Luego se hace un recorrido al indice de la tabla authors, el mismo indice que es creado por

la PRIMARY KEY. Finalmente los resultados son ordenados por el campo books.tittle

Page 14: Sacarle El Jugo a PostgreSQL

Los valores que se ven en paréntesis son el costo estimado y actual de esa parte de la consulta.

Cuanto menor sea la diferencia entre estos dos valores existeme un mejor desempeño.

Ahora vamos a cambiar un poco la estructura con la adición de un Index en books.author_id y

así evitar la busqueda secuencial.

CREATE INDEX books_idx1 on books(author_id);

Si se vuelve a ejecturar la consulta de nuevo usted no vera ningún cambio notable en la salida.

Estos es por que PostgreSQL no ha vuelto a analizar los datos y no ha determinado que el

nuevo index puede ayudar en la consulta. Esto se puede solucionar mediante la ejecución de:

ANALYZE books;

Puede que no note cambios en los resultados de la búsqueda en secuencia si la tabla no contiene

muchos registros. Si una consulta va a retornar una gran cantidad de datos, el planificador

selecciona una búsqueda en secuencia a través del indice, ya que es más rápido. Se puede forzar

PosgreSQL a favor de las búsquedas por indices sobre las búsquedas secuenciales fijando el

parámetro de configuración enable_seqscan = off . Esto no quita todas las búsquedas por

secuencia ya que algunas tablas pueden no tener indices pero si fuerza al planificador a utilizar

siempre una búsqueda por indices cuando estos estén disponibles y sin importar si la cantidad

de datos a retornar es mínima. Es recomendable hacer este cambio en la parte inicial de cada

conexión con a la base de datos, por medio del comando SET enable_seqscan = off , y no

hacerlo ampliamente en todas las bases de datos. Sin embargo desactivas esta opción se hace en

casos de pruebas y de realización de Tuning y no como opción de uso diario.

Generalmente la mejor forma de optimizar las consultas es usar indices en colúmnas específicas

y combinaciones de colúmnas que corresponden a las consultas más frecuentes.

Lamentablemente esto se hace por ensayo y error. También debe tener en cuenta que

incrementar el número de indices en una tabla incrementa el número de operaciones de

escritura que se deben realizar para cada INSERT y UPDATE. Así que no haga cosas tontas

como agregar indices a todas las colúmnas de una tabla.

Algo que puede ayudar es jugar con el nivel de las estadísticas que se recogen en una tabla o

columna con el comando:

ALTER TABLE <table> ALTER COLUMN <column> SET STATISTICS <number>;

Este valor puede ser un número entre 0 y 1000 y ayuda a PostgreSQL a determinar el nivel de

recopilación de estadísticas que se debe realizar en esta columna. Esto ayuda a controlar la

Page 15: Sacarle El Jugo a PostgreSQL

generación del plan de la consulta sin tener VACUUM lentos y analizar las operaciones debido

a la generación de grandes cantidades de estadísticas para todas las tablas y columnas.

Otra herramienta útil para ayudar a determinar como hacer Tuning a la base de datos son las

consultas al registro del sistema. Se puede decir a PostgreSQL que consultas del registro nos

interesan a través de la opción de configuración de log_statement. Esto es muy útil en

situaciones donde hay muchos usuarios realizando consultas tipo ad hoc() en el sistema a través

de algo como Crystal Reports o directamente vía PSQL.

Diseño y estructura de la base de datos

A veces el diseño y la estructura de la base de datos afecta el rendimiento. Por ejemplo si usted

tiene una tabla como la que se muestra a continuación:

CREATE TABLE employees ( id int4 PRIMARY KEY, active boolean, first_name varchar, middle_

name varchar, last_name varchar, ssn varchar, address1 varchar, address2 varchar, city va

rchar, state varchar(2), zip varchar, home_phone varchar, work_phone varchar, cell_phone

varchar, fax_phone varchar, pager_number varchar, business_email varchar, personal_email

varchar, salary int4, vacation_days int2, sick_days int2, employee_number int4, office_ad

dr_1 varchar, office_addr_2 varchar, office_city varchar, office_state varchar(2), office

_zip varchar, department varchar, title varchar, supervisor_id int4 );

El diseño es fácil de entender, pero no es muy bueno en varios niveles. Si bien dependerá de la

aplicación en particular, en la mayoría de casos usted no nececita acceder a todos los datos al

mismo tiempo.

Al romper esta tabla en tablas más pequeñas se puede conseguir que las consultas sean más

eficientes ya que PostgreSQL tiene que leer menos y eso sin tocar otros aspectos de

funcionalidad. Esta es una mejor manera de hacer las cosas:

CREATE TABLE employees ( id int4 PRIMARY KEY, active boolean, employee_number int4, first

_name varchar, middle_name varchar, last_name varchar, department varchar, title varchar,

email varchar ); CREATE TABLE employee_address ( id int4 PRIMARY KEY, employee_id int4, p

ersonal boolean, address_1 varchar, address_2 varchar, city varchar, state varchar(2), zi

p varchar ); CREATE TABLE employee_number_type ( id int4 PRIMARY KEY, type varchar ); CRE

ATE TABLE employee_number ( id int4 PRIMARY KEY, employee_id int4, type_id int4, number v

archar ); CREATE TABLE employee_hr_info ( id int4 PRIMARY KEY, employee_id int4, ssn varc

har, salary int4, vacation_days int2, sick_days int2 );

De esta manera esta unidad de información esta divida en grupos lógicos. La tabla principal

contiene la información más utilizada y las otras tablas almacenan el resto de información. El

beneficio adional de este diseño es que puede tener cualquier cantidad de teléfonos y

direcciones asociadas a un solo empleado de la tabla principal.

Page 16: Sacarle El Jugo a PostgreSQL

Otro consejo útil es utilizar los indices parciales en las columnas donde se consulta un cierto

valor con mayor frecuencia que otros. Tomemos, por ejemplo, la tabla empleados de arriba.

probablemente casi siempre se consultan los empleados que tengan estado activo, pero creando

un indice parcial para la columna cuando el valor es verdadero ayuda a incrementar la

velocidad de la consulta y puede ayudar a que el planeador decida usa el index en los casos en

que de otro modo no lo haría. Un index parcial se puede crear de la siguiente manera:

CREATE INDEX employee_idx2 ON employee(active) WHERE active='t';

Otros articulos relacionados a este y que le pueden ser de interés son:

Sistema de Bitácoras(Logs) en PostgreSQL

Compilando y poniendo en marcha PostgreSQL

Aspectos de Seguridad en PostgreSQL

Segunda Investigación

Algunos consejos generales para aumentar el

rendimiento

Dom, 29/03/2009 - 22:30 — rafaelma

Como hemos dicho muchas veces, no existe siempre la solución perfecta para

aumentar el rendimiento de nuestro sistema. Las bases de datos son sistemas

dinámicos que se utilizan de diferentes maneras y contienen diferentes tipos de datos.

Una configuración que funciona bien con un sistema, no tiene porque hacerlo con otro

y existen muchos factores que pueden afectar positiva y negativamente al

rendimiento.

Pero existen diferentes técnicas que se pueden usar aisladas ó en conjunto que ayudan

en muchos casos a mejorar el rendimiento. Aqui teneis una pequeña lista con algunos

consejos generales que suelen ayudar en muchas ocasiones cuando se necesita

Page 17: Sacarle El Jugo a PostgreSQL

mejorar el rendimiento. En esta lista no tendremos en cuanta las mejorias que se

pueden obtener con el uso adecuado de SQL y normalización de los datos.

Ejecutar VACUUM ANALYZE tan a menudo como sea necesario, Bien

manualmente ó ajustanto autovacuum si es necesario

Un sistema de discos de alto rendimiento suele ser más importante que la

cantidad de memoria disponible y esta a su vez más importante que la CPU

utilizada.

Un servidor de bases de datos nunca tendra suficiente memoria. Cuanta más

memoria, mejor.

Cuanto más discos disponibles en RAID, mejor. Usar Tablespaces para

organizar los datos.

RAID 1+0 / 0+1 suele funcionar mejor que RAID 5.

Saparar el registro de transacciones (ficheros WAL) del resto de datos, usar

diferentes discos.

Aumentar el valor de checkpoint_segments en sistemas con una alta concurrencia

de actualizaciones de los datos (insert,update,delete)

Discos SCSI y SAS som preferibles en servidores con un alto nivel de utilización

Múltiples CPUs ayudan a ejecutar/realizar trabajos paralelos en nuestras bases

de datos.

Ejecutar CLUSTER cuando sea viable en tablas con una alto nivel de

actualización de datos.

Utilizar un servidor dedicado siempre que sea posible. Será más facil de

configurar y ajustar para mejorar nuestro rendimiento.

Al inicializar/poblar una nueva base de datos con una gran cantidad de datos:

o Usar COPY en vez de INSERT

o Remover los indices durante la restauración de los datos.

o Aumentar el valor de maintenance_work_mem

o Aumentar el valor de checkpoint_segments

o fsync=false !! No olvidar cambiar este valor a TRUE cuando

termineis de restaurar los datos !!

o No olvidar ejecutar ANALYZE al termino de la restauración de los datos

Bueno, y hasta aqui los consejos generales, más adelante iremos profundizando en

aspectos concretos que pueden afectar al rendimiento.

Page 18: Sacarle El Jugo a PostgreSQL

Tercera Investigación

Aumentar el rendimiento Postgres

Muchas personas piensan que el aumento de rendimiento de una Base de Datos es sinonimo

de CPU, es decir mientras mejor es la CPU mejor es el rendimiento. Esto no es cierto porque

existen variantes más importantes que considerar al momento de tratar de sacar el mejor

provecho a nuestra Base de Datos.

Para empezar se debe usar Servidores Dedicados para Bases de Datos,

muchas pymes utilizan los Servidores como equipos de almaceanamiento, lo cual hace que un

servidor llegue a ser Servidor de Archivo, Correo y Base de Datos al mismo tiempo, cuando

fallan los sistemas siempre el culpable es la Base de Datos.

Actualizar a la ultima version de postgres, siempre es importante ir actualizando los sistemas a

la ultima version de Postgres (8.3 para produccion y 8.4 beta 2), para obtener un mejor

rendimiento, superara lo bug y no tener que lamentar problema indeseados.

Levantar un Servidor en linux, esta comprobado que Postgres obtiene el mejor rendimiento

con los Sistemas Operativos LINUX, eso no quiere decir que en Windows esto funcione mal.

La selección del tipo de disco a utilizar, es recomendable discos Duros de alto rendimiento

ojalas en RAID o para las empresas pequeñas SATA.

Utilizar la major cantidad de Memoria RAM posible.

Separar el fichero de Datos y Log, en unidades de Disco diferentes.

Para concluir es necesario que revisen los siguientes parametros

1. max_connections: aplica la cantidad máxima de conexiones de clientes

2. shared_buffers: determina cuanta memoria está dedicada a PostgreSQL para datos en caché

3. effective_cache_size:Este debe ser establecido en un monto estimado de cuanta memoria

está disponible para memoria intermedia en el disco para el sistema operativo

4. checkpoint_segments:PostgreSQL escribe las nuevas transacciones a la Base de Datos en

un archivo llamado segmentos del WAL que son de 16MB de tamaño

5. autovacuum:Vaccum significa 'vaciar' literalmente hablando. El proceso de VACUUM lo que

realiza es una limpieza de tuplas muertas que han sido marcadas como borradas o

modificadas, ya que el motor de base de datos no las borra inmediatamente de la parte física

para no sobrecargar las operaciones normales

para major informaión sobre estos parametros, diriguirse a wiki de postgres

Otros consejos para lograr una mejor optimización aqui (esta en ingles)

link interesantes:

Encontrando consultas que Consumen Recursos

Optimización del rendimiento (esta en ingles)