Upload
jonathan-d-perdomo
View
62
Download
4
Embed Size (px)
Citation preview
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.
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
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
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
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:
#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.
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
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
#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.
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
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
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
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
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
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.
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
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.
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)