Anda di halaman 1dari 113

Introducci on a PostgreSQL

Ing. Pedro Mu noz del Rio pmunoz@gmail.com Lima, Per u

Introducci on
PostgreSQL es un gestor de bases de datos relacionales que empez o como un proyecto de la universidad de Berkeley en California y su historia data desde los comienzos de las bases relacionales. Posee funcionalidades de corte empresarial como funciones para crear vistas, funciones agregadas para aplicar sobre las vistas entre otras. Tiene la capacidad de aceptar grandes cantidades de datos, como tablas con decenas de millones de registros sin mayor problema. Adem as de un gestor de bases de datos, PostgreSQL es una plataforma para aplicaciones y permite escribir procedimientos almacenados y funciones en diversos lenguajes como SQL, Python y Java entre otros, agregando los m odulos necesarios en el caso de los u ltimos. Conectarse a un web service a trav es de Python, usar funciones estad sticas de R y consultar los resultados con SQL es posible mediante PostgreSQL. Adem as, se pueden denir tipos propios de datos, instalar f acilmente extensiones mediante una sola instrucci on SQL y administrarlas con sencillez. Y como si fuera poco, Postgresql es multiplataforma, por lo cu al puede ser implementado tanto en Linux, BSD como Windows e incluso Mac OS, con binarios disponibles si no se desea compilar postgresql. Los lenguajes de programaci on m as populares tienen librer as que les permiten comunicarse con Postgresql y hacer consultas, entre los m as conocidos PHP, Python, Ruby, Java, .Net, Perl entre otros. Hoy en d a, PostgreSQL es una de las alternativas m as relevantes en el campo de las Bases de Datos relacionales, de c odigo abierto y utilizada por empresas de todo tama no a nivel mundial.

Indice
Introducci on 1. Arquitectura del Sistema 1.1. Breve historia . . . . . . . . . . . . . . . . . 1.2. Quienes utilizan PostgreSQL? . . . . . . . 1.2.1. Internacionales . . . . . . . . . . . . 1.3. Resumen de la Arquitectura . . . . . . . . . 1.3.1. Gesti on de la data . . . . . . . . . . 1.3.2. El procesamiento de una consulta . . 1.4. Multi-Version Concurrency Control (MVCC) 1.5. Write-Ahead Logging . . . . . . . . . . . . . 1.6. Objetos m as utilizados en PostgreSQL . . . 1.7. Nuevas funcionalidades en PostgreSQL 9.2 . 1.8. Limitaciones . . . . . . . . . . . . . . . . . . 1.9. Instalaci on . . . . . . . . . . . . . . . . . . . 2. Administraci on 2.1. Conguraci on de Postgresql . . . . . . . . 2.2. Creando Bases de Datos . . . . . . . . . . 2.2.1. Comando createdb . . . . . . . . . 2.2.2. Creando una base de datos plantilla 2.2.3. Eliminar una Base de Datos . . . . 2.3. Creando Esquemas . . . . . . . . . . . . . 2.3.1. Permisos . . . . . . . . . . . . . . . 2.3.2. Eliminar esquemas . . . . . . . . . 2.4. Ruta de B usqueda de Esquemas . . . . . . 2.4.1. Utilizaci on de los esquemas . . . . 2.5. Roles . . . . . . . . . . . . . . . . . . . . . 2.5.1. Crear un usuario . . . . . . . . . . 2.5.2. Atributos de los roles . . . . . . . . 2.6. Grupos . . . . . . . . . . . . . . . . . . . . 2.7. Control de Acceso . . . . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

1 1 1 1 3 3 5 5 6 6 7 7 7 11 11 14 15 16 17 18 21 24 25 27 27 29 31 32 36 38 38 40 41 41

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

3. Transacciones y concurrencia 3.1. Denici on de Transacci on . . . . . . . . . . 3.1.1. Savepoints . . . . . . . . . . . . . . . 3.2. Niveles de Aislamiento de las Transacciones 3.2.1. Detalle de los niveles de aislamiento .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

ii

3.3. Descripci on del Control de Concurrencia 3.4. Diferencias entre MVCC y Bloqueo . . . 3.5. Ejemplo MVCC . . . . . . . . . . . . . . 3.5.1. UPDATES . . . . . . . . . . . . . 3.5.2. DELETE . . . . . . . . . . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

50 50 51 51 52 54 54 55 55 55 56 56 56 56 57 57 59 59 59 60 61 62 63 68 68 69 71 71 72 73 74 74 75 76 79 79 80 83 87 91 103 103 103 103 104 105

4. Ajustes de rendimiento 4.1. Conguraci on de Hardware . . . . . . . . . . . . . . . . 4.1.1. CPU . . . . . . . . . . . . . . . . . . . . . . . . 4.1.2. Memoria . . . . . . . . . . . . . . . . . . . . . . 4.1.3. Discos . . . . . . . . . . . . . . . . . . . . . . . 4.2. Conguraci on del S.O. . . . . . . . . . . . . . . . . . . 4.2.1. Hdparm . . . . . . . . . . . . . . . . . . . . . . 4.2.2. Sistemas de archivos . . . . . . . . . . . . . . . 4.2.3. Journaling . . . . . . . . . . . . . . . . . . . . . 4.2.4. Sistemas de archivos de Linux . . . . . . . . . . 4.2.5. Conguraci on del sistema de archivos en Linux 4.2.6. BSD . . . . . . . . . . . . . . . . . . . . . . . . 4.3. Memoria para el cache de la Base de Datos . . . . . . . 4.3.1. Unidades de memoria en postgresql.conf . . . . 4.3.2. Cache de la Base de Datos . . . . . . . . . . . . 4.4. Conguraci on (postgresql.conf) . . . . . . . . . . . . . 4.4.1. postgresql.conf . . . . . . . . . . . . . . . . . . 4.4.2. Conguraci on de logs . . . . . . . . . . . . . . . 4.5. Conguraci on de un nuevo servidor . . . . . . . . . . . 4.5.1. Efectos del cache de la BD . . . . . . . . . . . . 4.6. Indices . . . . . . . . . . . . . . . . . . . . . . . . . . . 5. Ajustes de rendimiento II: Optimizaci on de las Bases 5.1. Data de ejemplo . . . . . . . . . . . . . . . . . . . . . . 5.2. Timing . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.3. Explain y Explain Analyze . . . . . . . . . . . . . . . . 5.4. Las consultas y la cache . . . . . . . . . . . . . . . . . 5.4.1. Efecto de la cache . . . . . . . . . . . . . . . . . 5.4.2. Estructura del plan de la consulta . . . . . . . . 5.4.3. Costo de computaci on . . . . . . . . . . . . . . 5.5. Optimizaci on de consultas . . . . . . . . . . . . . . . . 5.5.1. Armando conjuntos de registros . . . . . . . . . 5.5.2. Procesando los nodos . . . . . . . . . . . . . . . 5.5.3. Joins . . . . . . . . . . . . . . . . . . . . . . . . 5.5.4. Ordenamiento de Joins . . . . . . . . . . . . . . 5.5.5. Tips para optimizar SQL . . . . . . . . . . . . . 5.6. Par ametros para el planeamiento de consultas . . . . . 5.6.1. eective cache size . . . . . . . . . . . . . . . . 5.6.2. work mem . . . . . . . . . . . . . . . . . . . . . 5.6.3. Optimizando las consultas para la data en cache 5.7. Comprobar la equivalencia de un query . . . . . . . . . 5.8. EXPLAIN ANALYZE gr aco . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

de . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

datos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . .

iii

6. Alta disponibilidad y replicaci on 6.1. Replicaci on . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.1.1. Conceptos de replicaci on . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.1.2. Congurar una r eplica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7. Particionado de tablas 7.1. Particionado . . . . . . . . . . . . . . . . . . . 7.2. M etodos de Particionado . . . . . . . . . . . . 7.2.1. Conguraci on de Particionado . . . . . 7.3. Crear las particiones . . . . . . . . . . . . . . 7.3.1. Redirigir los INSERT a las particiones 7.3.2. Utilizar reglas de partici on . . . . . . . 7.3.3. Trigger para los Updates . . . . . . . . 7.3.4. Migraci on de la data . . . . . . . . . . 7.3.5. Crear nuevas particiones . . . . . . . . 7.3.6. Ventajas de las particiones . . . . . . . 7.3.7. Errores al particionar . . . . . . . . . . 8. Pooling de conexiones 8.1. El pool de conexiones . . . . . . . . . . . . . 8.2. PgBouncer . . . . . . . . . . . . . . . . . . . 8.2.1. Instalaci on de PgBouncer . . . . . . 8.2.2. Congurar PgBouncer . . . . . . . . 8.3. PgPool II . . . . . . . . . . . . . . . . . . . 8.3.1. Instalar PgPool II . . . . . . . . . . . 8.3.2. Conguraci on de PgPool II . . . . . 8.3.3. Preparar los nodos de bases de datos 8.3.4. Activar PgPool II . . . . . . . . . . . 8.3.5. Conectarse a PgPool II . . . . . . . . 9. Lenguajes Procedurales 9.1. Estructura de una funci on . . . . . 9.2. Funciones SQL . . . . . . . . . . . 9.3. Funciones PL/pgSQL . . . . . . . . 9.4. Funciones en PL/Python . . . . . . 9.4.1. Funci on python b asica . . . 9.4.2. Aspectos b asicos de Python 9.4.3. Ejemplo de Python . . . . . 9.4.4. Tipos b asicos . . . . . . . . 9.4.5. Operadores . . . . . . . . . 9.4.6. Colecciones . . . . . . . . . 9.4.7. Control de ujo . . . . . . . 9.4.8. Funciones . . . . . . . . . . 9.4.9. Funciones Trigger . . . . . .

107 107 107 108 111 111 112 112 113 115 118 119 120 125 125 125 126 126 126 127 127 130 130 130 131 131 131 133 133 135 139 139 140 144 144 145 147 148 150 152 152

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

10.Extensiones y contrib 154 10.1. Instalar Extensiones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154 10.2. Extensiones Comunes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155

iv

Lista de Gr acos
1.1. 1.2. 1.3. 1.4. 1.5. Arquitectura de PostgreSQL . . . Estructura del disco . . . . . . . . Indices . . . . . . . . . . . . . . . Procesamiento de una consulta [4] Pantalla principal de Pgadmin3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 3 4 5 8 20

2.1. Asignaci on de privilegios en Pgadmin3 . . . . . . . . . . . . . . . . . . . . . . . . . .

5.1. EXPLAIN ANALYZE gr aco en PgAdmin . . . . . . . . . . . . . . . . . . . . . . . . 105

Cap tulo 1 Arquitectura del Sistema


1.1. Breve historia

PostgreSQL,originalmente llamada Postgres, fue creada en la UCB (Universidad de California, Berkeley) por un profesor llamado Michael Stonebraker en 1986, como un sucesor de Ingres, un motor propiedad de Computer Associates y con el objetivo de avanzar el estado del arte en bases de datos relacionales. En 1996, luego de a nos de desarrollo en la academia, un equipo de desarrolladores fuera de Berkeley decide liberar el proyecto y hacerse cargo de sus desarrollo, trabajando varios a nos hasta liberar la primera versi on 6.0 en 1997. Desde el inicio fue un gestor de base de datos conocido por su estabilidad y con la ayuda de cientos de desarrolladores a nivel mundial, se fueron agregando nuevas funcionalidades como control de la concurrencia, nuevos tipos de datos, mayor perfomance, etc.

1.2.

Quienes utilizan PostgreSQL?

En el Per u y el mundo hay gran cantidad de empresas e instituciones que han conado uno de sus activos m as valiosos, su informaci on, a PostgreSQL, a continuaci on algunos ejemplos:

1.2.1.

Internacionales

U.S. Agency for International Development U.S. Centers For Disease Control and Prevention U.S. Department of Labor U.S. General Services Administration U.S. State Department IMDB.com, The Internet Movie Database

Macworld Sun Microsystems Red Hat Apple Fujitsu Cisco Skype

1.3.

Resumen de la Arquitectura

PostgreSQL tiene una arquitectura que incluye diversos m odulos que interactuan entre si. En el nivel m as alto sigue un esquema cliente-servidor mientras que en el acceso a datos utiliza un esquema por capas.

Gr aco 1.1: Arquitectura de PostgreSQL

El m odulo Libpq es el encardado de gestionar las comunicaciones entre el cliente y el postmaster (servicio de PostgreSQL en el servidor). El servidor esta compuesto por 2 grandes m odulos, el Postmaster que es el responsable de aceptar las comunicaciones con el cliente, autenticar y dar acceso. El Postgres se encarga de administrar los querys y comandos enviados por el cliente. PostgreSQL trabaja bajo el concepto de process per user, eso signica un solo proceso cliente por conexi on. El Storage Manager (Gestor de almacenamiento) es responsable de la gesti on del almacenamiento de los datos, controlar todos los trabajos del back-end incluido la administraci on del buer, archivos, bloqueos y control de la consistencia de la informaci on. Cuando se guarda la data en disco, esta es utilizada para consultas. Al leer la data, se extrae del disco para pasarla a la RAM, y al escribir se transere de la RAM al disco. [4]

1.3.1.

Gesti on de la data

La data en todo Gestor de Bases de Datos se guarda en bloques de disco llamados p aginas cuyo tama no var a entre 8KB y 32KB, las cuales se guardan en diferentes posiciones f sicas del disco, si se dispersan por el disco, causan menor rendimiento de la base de datos. En PostgreSQL cuando se realizan operaciones de lectura y/o escritura primero se consulta al Buer (RAM) si contiene la p agina, en caso no ser as , se obtiene del disco. Toda operaci on hace que PostgreSQL agregue data. Cuando se elimina un registro o se modica, PostgreSQL almacena una copia invisible hasta que ejecuta VACUUM y se libera de toda la data sobrante.

Gr aco 1.2: Estructura del disco Indices En los discos la data se almacena en bloques de datos llamados p aginas, estos bloques son accedidos por entero (operaci on at omica). Estos bloques est an estructurados como listas enlazadas, contienen una secci on de data y un puntero a la localizaci on del siguiente nodo. Debido a que los registros se buscan por campos, buscar en un conjunto de campos es necesario para encontrar los registros que se buscan en una consulta, pero al buscar en un campo cuyos datos no est an ordenados el tiempo de b usqueda escala junto con el tama no de la data. Un ndice es un archivo donde esta parte de la data y estructura de una tabla con las search key de b usqueda. Al crear un ndice en una tabla se crea otra estructura de datos que contiene el valor ordenado del campo y apunta al registro que lo contiene. Es recomendable crear ndices sobre datos que se repitan lo menos posible entre si. Los ndices representan un gran aumento en el rendimiento de un gestor de base de datos pero consumen espacio de disco por cada ndice que se cree. Debido a su capacidad de disminuir el tiempo de b usqueda en grandes tablas, solo debe ser utilizado con ese n.

Gr aco 1.3: Indices

1.3.2.

El procesamiento de una consulta

Gr aco 1.4: Procesamiento de una consulta [4] El cliente (libpq) se comunica con el servicio del postmaster para pasarle una cadena de texto con la consulta. El parser transforma la consulta en una serie de instrucciones que la base de datos puede interpretar, por eso es importante escribir bien las consultas. A continuaci on se analiza que lo escrito sea sint acticamente correcto y se descompone por token la consulta para pasarla a la estructura que le corresponde (select, update, grant, etc). El m odulo Trac Cop contiene al controlador principal del proceso del PostgreSQL, adem as se encarga de las comunicaciones entre el Parser, Optimizer, Executor y commands functions. Las consultas complejas pasan al Rewriter (select,insert, etc.), las que no, se pasan al Utility Commands, en general

consulta simples (alter, create, vacuum, etc). El m odulo planner es el encargado de generar el plan de ejecuci on, esto es estimar la mejor v a para resolver el query, maneja mediante formulas matem aticas avanzadas la forma de b usqueda de datos y la forma de resolver las relaciones entre tablas. Luego que el planner calcula la forma m as eciente de ejecutar la consulta se la pasa al Executor que la lleva a cabo. [4]

1.4.

Multi-Version Concurrency Control (MVCC)

Una decisi on de dise no importante que se debe tomar en toda BD es como gestionar la interacci on de m ultiples clientes con la misma data. PostgreSQL utiliza un enfoque llamado Multiversion Concurrency Control (control multiversi on de la concurrencia) el cu al es tambi en utilizado en otras Bds como Oracle. Mediante el control de concurrencia el gestor permite que muchos usuarios puedan acceder a la misma data al mismo tiempo. Cada proceso de usuario ejecuta transacciones las que a su vez pueden contener una o m as operaciones. Las transacciones deben cumplir el criterio ACID:

A tomicity: todas las acciones en la transacci on se cumplen o no se cumple ninguna. C onsistency: la transacci on solo termina si la data es consistente. I solation: la transacci on es independiente de otras transacciones. D urability: cuando la transacci on termina el resultado de la misma permanece. Bajo el MVCC, la implementaci on de concurrencia de PostgreSQL, las transacciones ven una imagen de la data al momento de empezar (para eso la data se versiona con un timestamp), esto protege la transacci on de inconsistencia de data cuando llegan varias operaciones de Lectura/escritura sobre el mismo registro. La data no se modica o elimina, solo se agregan nuevos registros y los antiguos pasan a ser invisibles. La nueva data no es visible para otras transacciones hasta que no termina la actual transacci on y es enviada (committed) a la base de datos.

1.5.

Write-Ahead Logging

Es el m etodo est andar en los gestores de bases de datos para asegurar la integridad de la data. El concepto central de WAL es que los cambios a los archivos de data (donde las tablas y los ndices residen) solo deben ser escritos despu es que los cambios han sido registrados, esto es, despu es de que los registros de logs describiendo los cambios se hayan guardado de forma permanente. Esto sirve para que en caso de un desastre, se pueda recuperar la Bd utilizando el log del servidor. El par ametro wal level de postgresql.conf determina cuanta informaci on es registrada en el WAL. Las alternativas son tres: minimal (opci on por defecto), archive y hot standby.

En el nivel minimal, no se registran algunas operaciones como CREATE TABLE AS o CREATE INDEX pero este nivel no guarda suciente informaci on como para reconstruir la data de la BD desde el WAL. Para poder llevar a cabo replicaci on se necesita utilizar los niveles archive o hot standby. La diferencia entre ambos es que hot standby no solo registra todos los cambios en la data sino adem as las transacciones as sea de solo lectura

1.6.

Objetos m as utilizados en PostgreSQL

El servidor PostgreSQL tambi en conocido como servidor o demonio, se puede tener m as de uno en un servidor siempre y cuando utilicen diferentes puertos o ips y almacenen su data en ubicaciones diferentes. Base de datos, cada servidor puede tener varias bases de datos. Tablas, son la principal herramienta de toda base de datos. Esquemas, son parte del est andar ANSI-SQL, y son los contenedores l ogicos de tablas y otros objetos. Cada base de datos puede tener diferentes esquemas. Tablespace, es la localizaci on f sica donde la data es almacenada. Postgresql permite que se gestionen de forma independiente, lo que signica que se pueden mover las bases de datos a otras particiones o discos con pocos comandos. Vistas, se utilizan para abstraer las consultas y en PostgreSQL adem as pueden ser actualizadas. Funciones, en Postgresql pueden retornar un solo valor o un set de registros. Operador, son funciones simb olicas que tienen el respaldo de una funci on, en PostgreSQL se pueden denir por el usuario. Cast, permite convertir de un tipo a otro y es soportado por funciones que realmente hacen la conversi on. En PostgreSQL los usuarios pueden crear sus propias funciones de conversi on. Sequence, controlan los n umeros autoincrementales en las deniciones de las tablas. Se crean autom aticamente cuando se dene una columna serial. Triggers, son los disparadores de acciones al detectar cambios en la data. Data externa, en postgresql se puede hacer consultas fuentes externa de data ya sea que esa fuente sea otra BD relacional, un archivo plano, una Bd NoSql, un web service, etc. Extensiones, agrupan funciones, tipos, casts, indices en una sola unidad para mayor mantenibilidad. Es sobre todo usar para instalar m odulos adicionales.

1.7.

Nuevas funcionalidades en PostgreSQL 9.2

Algunas de las nuevas funcionalidades de Postgresql 9.2 son: [3] Acelerar la consulta de columnas pertenecientes a un index.

Mejoras en el ordenamiento que optimizan operaciones de ordenamiento en memoria hasta un 20 %. Mejoras en el planeamiento de consultas. Replicaci on en cascada ahora soporta streaming de un esclavo a otro esclavo. ALTER TABLE IF EXISTS sintaxis para hacer cambios en tablas. M as opciones para ALTER TABLE. M as opciones para crear y restaurar backups. La posibilidad de crear funciones en javascript mediante plv8js. El tipo JSON como tipo nativo de Postgresql. Las funciones SQL pueden referirse a los argumentos por nombre y no por n umero.

1.8.

Limitaciones

PostgreSQL por su naturaleza de BD para servidores, no es aplicable para ser embebida como SQLite o Firebird. Adem as, en muchos hostings por uno u otro motivo no est a presente PostgreSQL, aunque ese es un problema que se est a solucionando con el tiempo.

1.9.

Instalaci on

Para instalar en Ubuntu la versi on 9.2 de PostgreSQL llevamos a cabo los siguientes pasos: Instalar las librer as requeridas sudo apt-get install libpq-dev Agregar el repositorio donde est a ubicado PostgreSQL 9.2 (no est a a un en los repositorios ociales). sudo add-apt-repository ppa:pitti/postgresql Actualizar la lista de paquetes disponibles: sudo apt-get update Instalar el servidor sudo apt-get install postgresql-9.2 Poner a punto el servidor: Ingresar en el template1 de Postgresql para cambiar la contrase na del usuario por defecto. sudo su postgres -c psql template1 Cambiar la contrase na del usuario postgres.

postgres=# ALTER USER postgres WITH PASSWORD qwerty; Salimos del cliente psql. \q Eliminamos la contrase na del usuario postgres en el sistema sudo passwd -d postgres Se utiliza su para cambiar el password del usuario postgres sudo su postgres -c passwd Se crea el usuario pedro con el usuario del servidor postgres sudo -u postgres createuser -D -A -P pedro Crear la DB sudo -u postgres createdb -O pedro Bd prueba Para instalar Pgadmin: sudo apt-add-repository ppa:voronov84/andreyv sudo apt-get update sudo apt-get install pgadmin3

Gr aco 1.5: Pantalla principal de Pgadmin3

Auto Explain Otra opci on muy utilizada despu es de la versi on 8.4 de PostgreSQL es el m odulo auto explain que permite analizar la duraci on de una consultada viendo su plan EXPLAIN asociado. Para habilitarlo se debe agregar en postgresql.conf los siguientes par ametros y reiniciar el servidor: shared preload libraries = auto explain custom variable classes = auto explain auto explain.log min duration = 1s as de un segundo reEsta conguraci on va a ejecutar auto explain en toda consulta que dure m gistr andola con un plan EXPLAIN completo.

10

Ejercicios: 1. Instalar el servidor Postgresql. 2. Crear una base de datos llamada Base curso. 3. Crear un usuario llamado usuario curso. 4. Crear la tabla Persona de propiedad del usuario usuario curso con los siguientes campos: 5. nombre, apellidop, apellidom. 6. Insertar el nombre y apellidos de tres alumnos en la tabla.

11

Cap tulo 2 Administraci on


2.1. Conguraci on de Postgresql

Los archivos utilizados para congurar postgresql son tres: [3] postgresql.conf : El principal archivo de conguraci on de postgresql, controla conguraciones generales como la cantidad de memoria RAM a utilizar, la localizaci on f sica de las bases de datos, las ips a las que escucha postgresql, la conguraci on de los logs, etc. pg hba.conf : controla la seguridad, gestiona el acceso al servidor indicando que usuarios pueden acceder a que BD, que Ips o grupos de Ips est an permitidos de conectarse y el esquema de autenticaci on esperado. pg ident.conf : Es el archivo que mapea los usuarios del SO con los usuarios del servidor Para conocer donde est an localizados en el sistema, se puede utilizar un superusuario del servidor para ejecutar la siguiente consulta: $ sudo su postgres -c psql -d Bd prueba Y luego:

SELECT name, setting FROM pg_settings WHERE category = File Locations; Una forma sencilla de ver las conguraciones en postgresql.conf es consultar la tabla pg settings, por ejemplo la siguiente consulta devuelve los valores de seis par ametros de postgresql.conf.

12

SELECT name, context, setting, boot_val, reset_val FROM pg_settings WHERE name in (listen_addresses,max_connections,shared_buffers,effective_cache_size, work_mem, maintenance_work_mem) ORDER BY context,name; Tambi en se puede utilizar el comando show para ver cada par ametro de conguraci on por separado con su valor respectivo, por ejemplo:

show maintenance_work_mem; show work_mem; show all;

2.2.

Creando Bases de Datos

La forma m as sencilla de crear una base de datos es ingresando a un cliente (como psql) y utilizando el comando:

CREATE DATABASE mi_bd; El due no de la Bd ser a el usuario en el sistema y la BD ser a una copia de template1. Es potestad del creador de una Base de Datos eliminarla posteriormente, lo cu al elimina a su vez todos sus objetos como tablas, ndices, funciones, etc as tengan otros due nos. La primera base de datos en ser creada al instalarse PostgreSQL es postgres y luego template0 y template1 que son plantillas de bases de datos desde las cu ales se copian las nuevas bases en ser creadas. Todo cambio que se haga en template1 se replicar a en toda nueva Base de datos, por lo que se recomienda ser muy prudente con las plantillas. Si se desea crear una base de datos con otro due no fuera del usuario que la est a creando, se agrega el par ametro OWNER. Por ejemplo:

CREATE DATABASE nombre_db OWNER usuario_curso; Solo el superusuario puede crear una base de datos para otro usuario.

13

2.2.1.

Comando createdb

Como conveniencia se puede utilizar el comando createdb desde la terminal: createdb nombre db Lo que hace createdb es conectarse a la base de datos postgres y ejecuta CREATE DATABASE utilizando el usuario del sistema desde el cu al se le ejecuta. Mediante par ametros se puede utilizar createdb de forma m as vers atil, con -O se indica el owner de base de datos creada, con -U el usuario con el se conectar a a postgres entre otros par ametros. Por ejemplo: createdb -U postgres -O usuario curso nueva bd Va a crear una base de datos llamada nueva bd mediante el usuario postgres y va a ser propiedad de usuario curso.

2.2.2.

Creando una base de datos plantilla

Una base de datos de plantilla (Template DB) es una base de datos que sirve de plantilla para crear otras bases de datos. Se puede crear una Bd a partir de cualquier otra Bd, pero PostgreSQL permite que se denan Bds espec camente de plantilla. La principal diferencia es que una Bd denida como template no puede ser eliminada y puede ser utilizada por cualquier usuario con capacidad de crear bases de datos como plantilla para una nueva BD. La principal base de datos plantilla es template1 a partir de la cual se crean todas las bases de datos en caso no se mencione otra plantilla. Si se agregan objetos a template1, se replicar an en todas las nuevas bases que se creen teniendo a template1 como plantilla. Existe una segunda plantilla, template0, que contiene el mismo contenido inicial que template1. A diferencia de la segunda, template0 nunca debe ser modicada, ya que al crear una base de datos tomando como plantilla template0, se crea una base limpia de todo cambio posterior, lo cu al es especialmente valioso al restaurar un backup de pg dump ya que debe ser restaurado sobre una base de datos sin modicaci on alguna. Para crear una copia de template0 se ejecuta:

CREATE DATABASE dbname TEMPLATE template0; O desde la terminal: createdb -T template0 dbname Adem as de las plantillas predeterminadas, se pueden utilizar otras bases de datos como plantillas, con la limitante de que ninguna otra sesi on puede estar conectada a la base de datos fuente mientras es copiada.

14

Si se ha dise nado una Bd y se quiere convertirla en una plantilla, se ejecuta el siguiente comando como superusuario:

UPDATE pg_database SET datistemplate=true WHERE datname=mi_bd;

2.2.3.

Eliminar una Base de Datos

Las bases de datos se destruyen con el comando DROP DATABASE.

DROP DATABASE nombre_db; Solo el due no de una base de datos puede eliminarla. Eliminar una Base de datos implica destruir todo su contenido y es una acci on que no puede ser deshecha. No se puede ejecutar el comando DROP DATABASE mientras se est a conectado a la base de datos a ser eliminada, se debe hacerconectado desde otra base de datos. Existe un comando de consola, dropdb, para eliminar bases de datos. dropdb nombre db

2.3.

Creando Esquemas

Los esquemas son una forma l ogica de partir una base de datos en mini contenedores. Se pueden dividir los esquemas por funcionalidad, usuarios o cualquier otro atributo que se desee. Adem as de la partici on l ogica, proveen una forma sencilla de repartir privilegios. Para crear un esquema en una BD, nos conectamos a la Bd y ejecutamos el comando:

CREATE SCHEMA mi_esquema; Para acceder a un objeto en un esquema se escribe el nombre del esquema seguido por el nombre ddel objeto separados por un punto. schema.table Esta forma de nombrar una tabla funciona para toda aplicaci on, incluyendo comandos para modicar la tabla, leer y escribir datos. Para crear una tabla en el nuevo esquema se debe utilizar:

CREATE TABLE mi_esquema.mitabla (...);

15

La ruta por defecto (search path) denida en postgresql.conf es $user, public. Lo cual signica que si hay un esquema con el mismo nombre que el del usuario en el sistema, entonces todos los objetos van a revisar primero el esquema con el mismo nombre del usuario y luego el esquema p ublico. Los esquemas son tambi en utilizados para abstraer los nombres de las tablas, debido a que el nombre solo debe ser u nico dentro del esquema y muchas aplicaciones explotan esta caracter stica creando tablas con el mismo nombre en diferentes esquemas de tal manera que se carga una diferente dependiendo del usuario en el sistema. Los esquemas sirven por ejemplo para incluir m odulos externos (contrib) dentro de un esquema de tal manera que los nombres de sus objetos no puedan entrar en conicto con el nombre de los objetos de la BD. Se puede pensar en esquemas como en directorio pero sin la posibilidad de ser anidados. Otra forma de asignar permisos es mediante Pgadmin3, el cu al tiene una completa interfaz para asignar permisos.

Gr aco 2.1: Asignaci on de privilegios en Pgadmin3

16

2.3.1.

Permisos

Si se quiere dar permisos a un esquema que reci en se ha creado, se van a utilizar los comandos ALTER DEFAULT PRIVILEGES y GRANT. Por ejemplo, para que todos los usuarios de una BD tengan acceso a EXECUTE y SELECT en todas las tablas y funciones de un esquema que se creen a partir del momento en que se ejecuten se utilizar an los siguientes comandos:

GRANT USAGE ON SCHEMA contrib TO public; ALTER DEFAULT PRIVILEGES IN SCHEMA contrib GRANT SELECT, REFERENCES, TRIGGER ON TABLES TO public; ALTER DEFAULT PRIVILEGES IN SCHEMA contrib GRANT SELECT, UPDATE ON SEQUENCES TO public; ALTER DEFAULT PRIVILEGES IN SCHEMA contrib GRANT EXECUTE ON FUNCTIONS TO public; ALTER DEFAULT PRIVILEGES IN SCHEMA contrib GRANT USAGE ON TYPES TO public; Si el esquema ya est a denido con sus tablas y funciones, se pueden dar permisos uno por uno o darle permisos a todos mediante GRANT .. ALL .. IN SCHEMA.

GRANT USAGE ON SCHEMA contrib TO public; GRANT SELECT, REFERENCES, TRIGGER ON ALL TABLES IN SCHEMA contrib TO public; GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA contrib TO public; GRANT SELECT, UPDATE ON ALL SEQUENCES IN SCHEMA contrib TO public; Es com un buscar que un esquema sea propiedad de otro usuario, para asi restringir las actividades de los usuarios a namespaces restringidos. La sintaxis es:

CREATE SCHEMA nuevo_esquema AUTHORIZATION usuario_curso; Los esquemas cuyo nombre empieza con pg son utilizados el sistema y no se recomienda su creaci on por los usuarios debido a que futuras versiones de Postgresql pueden utilizar el nombre elegido. 17

Cuando no se dene expl citamente un esquema, el objeto creado entra en el esquema public, por lo cual es igual escribir:

CREATE TABLE productos ( ... ); Y

CREATE TABLE public.productos ( ... );

2.3.2.

Eliminar esquemas

Para eliminar un esquema este debe estar vacio (todos los objetos en su interior deben haber sido eliminados) y se utiliza:

DROP SCHEMA myschema; Para eliminar un esquema incluyendo todos sus objetos utilizar:

DROP SCHEMA myschema CASCADE;

2.4.

Ruta de B usqueda de Esquemas

Los nombres completos incluyendo el del esquema son tediosos de escribir, adem as de que no es bueno hardcodear los nombres de los esquemas en las aplicaciones. Al llamar a las aplicaciones solo por su nombre, el sistema determina que tabla es buscando en todos los esquemas presentes. El primer objeto con el nombre indicado que encuentre es escogido como el buscado. El primer esquema en la ruta de b usqueda (search path) es llamado el esquema actual (current schema), adem as de ser el primer esquema en la ruta de b usqueda es tambi en el esquema por defecto donde se crearan las nuevas tablas si no se especica un esquema en particular. Para ver la actual ruta de b usqueda se utiliza:

SHOW search_path; Para colocar un nuevo esquema en la ruta de b usqueda:

SET search_path TO miesquema,public;

18

Lo cual har a que el nuevo esquema sea el primero en la ruta de b usqueda, si queremos dejar de considerar public en la ruta de b usqueda se utiliza:

SET search_path TO miesquema;

2.4.1.

Utilizaci on de los esquemas

Los esquemas se pueden utilizar para organizar la data de muchas formas diferentes. Algunos patrones de uso son recomendados: Si no se crean esquemas todos los usuarios acceden al esquema public. Esta conguraci on es recomendada cuando hay solo un usuario o pocos usuarios cooperantes en la base de datos. Se puede crear un esquema para cada usuario con su propio nombre. Si se usa esta conguraci on se pueden revocar los permisos de los usuarios sobre el esquema public de tal manera que solo puedan utilizan sus propios esquemas. Para instalar aplicaciones compartidas es recomendable colocarlas en sus propios esquemas y dar permisos a todos los usuarios para acceder a ese esquema. Los usuarios pueden referirse a los objetos agregados por su nombre completo o agregar el nuevo esquema en la ruta de b usqueda.

2.5.

Roles

En PostgreSQL solo existe un tipo de cuenta y es la de rol. Si el rol puede ingresar a la BD, es un usuario. Los roles puede ser parte de otros roles y cuando un rol tiene miembros, es llamado un grupo. Los roles pueden ser due nos de objetos en las bases de datos (tablas por ejemplo) y pueden asignar privilegios a otros roles en esos objetos para controlar quien accede. Adem as, es posible hacer a un rol miembro de otros roles de tal manera que utilice sus privilegios. Los roles de PostgreSQL no son iguales a los usuarios del sistema operativo, en la pr actica puede ser u till mantener la correspondencia entre ambos pero no es necesario. Para crear un rol se utiliza CREATE ROLE :

CREATE ROLE name; Y para eliminarlo se usa DROP ROLE:

DROP ROLE name; Para saber que roles han sido creados utilizar:

19

SELECT rolname FROM pg_roles; O el comando \du.

2.5.1.

Crear un usuario

Al terminar de instalar el gestor de Bds, se crea por defecto una cuenta llamada postgres con una base de datos llamada postgres. Antes de hacer nada, se debe entrar con este usuario mediante psql o pgadmin y crear otros usuarios. La diferencia entre un rol y un usuario es que el usuario es creado con el atributo LOGIN que le permite ingresar a una base de dato. $ sudo su postgres -c psql -d postgres Mediante este comando SQL se crea un usuario con capacidad de crear bases de datos.

CREATE ROLE leo LOGIN PASSWORD qwerty CREATEDB VALID UNTIL infinity; Innity es una opci on por defecto por lo que no necesita ser considerada. Se puede incluir una fecha en la cual se espera que la cuenta desaparezca. Con otro comando SQL se crea un super usuario pero con un tiempo de vida limitado. Solo se puede crear un superusuario siendo un superusuario.

CREATE ROLE regina LOGIN PASSWORD 123456 SUPERUSER VALID UNTIL 2020-10-20 23:00;

2.5.2.

Atributos de los roles

Un rol puede tener diversos atributos que denan sus privilegios.

Login: solo los roles que tienen el atributo LOGIN pueden ser utilizados como el nombre inicial a utilizar en una conexi on a una base de datos. Superuser: Un superusuario de una base de datos pasa por encima de toda restricci on excepto al ingresar al sistema. Es un privilegio peligroso y debe ser otorgado con mucho cuidado. Para crear un nuevo superusuario utilizar: CREATE ROLE name SUPERUSER. Solo un superusuario puede crear otro superusuario. database creation: A un rol se le debe dar de forma expl cita el permiso para crear bases de datos. Para lograrlo se utiliza CREATE ROLE name CREATEDB. role creation: Para que un rol pueda crear otros roles se utiliza CREATE ROLE name CREATEROLE. initiating replication: Para que un rol pueda iniciar una replicaci on se debe dar permisos de replicaci on de login CREATE ROLE name REPLICATION LOGIN.

20

password: Un password solo es importante si el m etodo de autenticarse exige su utilizaci on. Los m etodos de autenticaci on password y md5. Para crear un password se utiliza CREATE ROLE name PASSWORD string. Cambiar atributos Para cambiar los atributos de un rol se utiliza ALTER ROLE. Por ejemplo:

ALTER ROLE davide WITH PASSWORD hu8jmn3; ALTER ROLE miriam CREATEROLE CREATEDB; ALTER ROLE worker_bee SET maintenance_work_mem = 100000;

2.6.

Grupos

Con frecuencia se agrupan usuarios para facilitar la gesti on de sus privilegios. De esta manera los privilegios pueden ser otorgados o revocados en grupo. Los roles de grupo son roles que no tienen permiso para ingresar en el sistema pero tienen otros roles como miembros. Son en general una forma de que un conjunto de usuarios comparta permisos en com un. Se puede crear un rol de grupo con:

CREATE ROLE jungle INHERIT; Y asignar otro usuario a ese grupo mediante:

GRANT jungle TO leo; Tal como se muestra, al crear un rol para convertirlo en un grupo, este debe ser capaz de heredar sus permisos. Para remover miembros de un grupo se utiliza REVOKE.

REVOKE leo FROM jungle; Los miembros de un grupo pueden utilizar sus privilegios de dos formas: Los miembros de un grupo pueden utilizar SET ROLE para convertirse momentaneamente en el grupo. En este estado la sesi on tiene acceso a los privilegios del role de grupo en vez de los privilegios

21

originales con los que se registro y cualquier objeto creado ser a propiedad del rol de grupo. En segundo lugar los roles miembros que tengan el atributo INHERIT tienen acceso a los privilegios de los roles de los que son miembros, incluyendo cualquier privilegio heredado por esos roles. Por ejemplo:

CREATE ROLE joe LOGIN INHERIT; CREATE ROLE admin NOINHERIT; CREATE ROLE wheel NOINHERIT;

GRANT admin TO joe; GRANT wheel TO admin; Al conectarse como joe, la sesi on tiene los permisos de admin pero no los de wheel. Si se ejecuta:

SET ROLE admin; La sesi on solo tendr a los privilegios de admin debido a que no hereda.

2.7.

Control de Acceso

PostgreSQL dispone de varios m etodos de autenticaci on para validar usuarios. El tipo de m etodo se dene en pg hba.conf. Los cinco tipos son:

trust: Cona en el usuario que se conecta. Solo valida que su IP y usuario sean correctos sin importar la contrase na. Es la m as com un en bases de datos instaladas en una computadora para un solo usuario. Md5: Es el m as com un de los m etodos y requiere un password cifrado mediante md5. Password: signica autenticarse mediante un password en texto plano. Ident: utiliza el SO para identicar si existe la cuenta del usuario intentando conectarse en el SO. No utiliza password. Para denir el tipo de autenticaci on se utiliza el archivo pg hba.conf, este archivo de conguraci on controla que usuarios pueden conectarse al servidor PostgreSQL.

22

Ejercicios: 1. Congurar PostgreSQL para que pueda ser accedido desde toda IP. 2. Crear una base de datos llamada Base plantilla y convertirla en una plantilla. 3. Agregar dos tablas a Base plantilla. 4. Crear una base de datos llamada base copia tomando como base a Base plantilla. 5. Crear un esquema llamado esquema curso propiedad de usuario curso. 6. Crear un usuario llamado usuario prueba. 7. Crear un esquema llamado esquema prueba propiedad de usuario prueba. 8. Crear una tabla Producto en ambos esquemas con los campos nombre, precio y cantidad. 9. Insertar datos diferentes en ambas tablas. 10. Ordenar los esquemas de manera tal que al escribir SELECT * FROM Productos se vea en pantalla la tabla Productos de esquema prueba. 11. Crear un usuario llamado usuario creador y darle permiso para crear bases de datos, esquemas y roles. 12. Crear bases de datos, esquemas y roles utilizando a usuario creador. 13. Crear un grupo llamado grupo prueba. 14. Hacer a usuario prueba miembro de grupo prueba.

23

Cap tulo 3 Transacciones y concurrencia


PostgreSQL provee las herramientas para gestionar el acceso concurrente a la data. La consistencia de la data es mantenida internamente utilizando un modelo de multiversi on (Multiversion Concurrency Control, MVCC). Esto signica que al consultar una Base de Datos cada transacci on ve una instant anea de la data tal como era alg un tiempo antes, sin importar el estado actual de la data subyacente. Esto protege a la transacci on de ver data inconsistente que puede haber sido causada por otras transacciones concurrentes en los mismos registros. Proveyendo aislamiento de la transacci on para cada sesi on en la BD. La principal ventaja de utilizar el modelo MVCC de control de la concurrencia en vez del bloqueo de registros es que en MVCC los bloqueos por leer data no intereren con los bloqueos por escribir data en un registro as las operaciones no se bloquean entre si. [2]

3.1.

Denici on de Transacci on

Las transacciones son uno de los conceptos fundamentales de todos los sistemas de bases de datos. El punto esencial es que una transacci on engloba un m ultiples pasos en una sola operaci on donde se ejecuta todo o nada. Los pasos intermedios antes de culminar la transacci on no son visibles para las transacciones concurrentes y si alguna falla ocurre, que evita que la transacci on se complete, ninguno de los pasos previos afecta a la base de datos. Si un conjunto de operaciones de una transacci on afectan a varios tablas en una base de datos, si una sola de las operaciones falla, todas las dem as operaciones quedan sin efecto y la base de datos no es modicada por la transacci on. Por ejemplo, si en un banco se realiza una transferencia entre dos cuentas y una operaci on resta dinero de una cuenta pero otra operaci on no puede a sumarlo al destinatario, toda la transacci on se cancela. Una transacci on es at omica, desde el punto de vista de otras transacciones o se lleva a cabo completamente o no en absoluto, adem as, antes de darse por terminada la transacci on, todas las actualizaciones hechas la BD son guardadas en almacenamiento permanente (p. ej. disco duro). Dadas las siguientes operaciones:

UPDATE accounts SET balance = balance - 100.00

24

WHERE name = Alice; UPDATE branches SET balance = balance - 100.00 WHERE name = (SELECT branch_name FROM accounts WHERE name = Alice); UPDATE accounts SET balance = balance + 100.00 WHERE name = Bob; UPDATE branches SET balance = balance + 100.00 WHERE name = (SELECT branch_name FROM accounts WHERE name = Bob); Los detalles de los comandos no son importantes, lo crucial es que hay varias actualizaciones envueltas en una sola operaci on.El banco por supuesto desea estar seguro de que las transacciones realizadas tengan exito todas o ninguna se lleve a cabo, caso contrario la data guardada no sera coherente. Para garantizar que situaciones as no se produzcan se agrupan las operaciones en transacciones. Una transacci on adem as debe de ser registrada y guardada de forma permanente antes de reportarse como terminada. Otra propiedad importante de las transacciones es el aislamiento: cuando m ultiples transacciones est an ejecutandose al mismo tiempo, cada una no debe de ser capaz de ver los cambios incompletos llevados a cabo por otros. Por ejemplo, si una transacci on est a ocupada cuadrando los balances de caja no deber a ver solo la transacci on iniciada por Alice o Bob, sino el resultado nal de toda la transacci on. Es por esto que las transacciones deben ser todo o nada no solo en sus efectos permanentes en la base de datos sino en la visibilidad de sus resultados a medida que avanza. Es por esto que los resultados de una transacci on son invisibles para otras transacciones hasta que la transacci on termina, donde todos los cambios a la data se vuelven visibles simultaneamente. En PostgreSQL una transacci on se lleva a cabo utilizando los comandos BEGIN y COMMIT al inicio y n de la transacci on, por ejemplo:

BEGIN; UPDATE accounts SET balance = balance - 100.00 WHERE name = Alice; -- etc etc COMMIT; Si en alg un punto de la transacci on decidimos no hacer commit, podemos eliminar todos los cambios mediante el comando ROLLBACK. Por defecto, PostgreSQL trata a cada comando SQL como una transacci on, colocando BEGIN al inicio de la transacci on y COMMIT al nal si es exitosa.

25

3.1.1.

Savepoints

Es posible controlar las operaciones en una trasacci on de una forma m as na mediante el uso de savepoints. Los savepoints permiten descartar selectivamente partes de una transacci on y enviar (commit) el resto a la BD. Despu es de denir un Savepoint en una transacci on , se puede hacer ROLLBACK TO de regreso al savepoint. Todos los cambios a la base de datos entre la denici on del Savepoint y el rollbak son descartadas, pero los cambios previos al Savepoint son guardados. Se puede regresar a un savepoint varias veces en el transcurso de una transacci on. Regresando al ejemplo del banco, la transacci on podr a ser la siguiente:

BEGIN; UPDATE accounts SET balance = balance - 100.00 WHERE name = Alice; SAVEPOINT my_savepoint; UPDATE accounts SET balance = balance + 100.00 WHERE name = Bob; -- En realidad mejor utilizamos la cuenta de Wally ROLLBACK TO my_savepoint; UPDATE accounts SET balance = balance + 100.00 WHERE name = Wally; COMMIT; ROLLBACK es la u nica manera de recuperar el control de una transacci on que ha sido bloqueada por el sistema debido a un error en una de sus transacciones.

3.2.

Niveles de Aislamiento de las Transacciones

Existen cuatro niveles de aislamiento de las transacciones en el est andar SQL, cada uno de los cuales permite que se lleven o no a cabo tres comportamientos. Los comportamientos son: Dirty read: Una transacci on lee data escrita por una transacci on a un no enviada (commited). Nonrepeatable read: Una transacci on vuelve a leer data que ha leido previamente y encuentra que ha sido modicada por otra transacci on que env o data despu es de enviada la actual transacci on. Phantom read: Una transacci on vuelve a ejecutar una consulta que devuelve un conjunto de registros que satisfacen determinada condici on de b usqueda y encuentra que este conjunto de registros a cambiado debido a otra transacci on concurrente. Los cuatro niveles y sus respectivos comportamientos seg un PostgreSQL:

26

Isolation Level Read uncommitted Read committed Repeatable read Serializable

Dirty Read Not possible Not possible Not possible Not possible

Nonrepeatable Read Possible Possible Not possible Not possible

Phantom Read Possible Possible Not possible Not possible

Tabla 3.1: Niveles de aislamiento Como se puede observar, Read uncommitted y Read commited son iguales seg un la implementaci on de PostgreSQL y el valor adicional de Serializable sobre Repeteable Read es el monitoreo para evitar que transacciones concurrentes no puedan ser serializadas. Read uncommitted se mantiene para nes de compatibilidad.

3.2.1.

Detalle de los niveles de aislamiento

Los niveles de aislamiento (isolation levels) son un aspecto central en el manejo de las transacciones por lo cual lo abordaremos con detalle. Para establecer el nivel de aislamiento de una transacci on se utiliza SET TRANSACTION.

SET TRANSACTION ISOLATION LEVEL { SERIALIZABLE | REPEATABLE READ | READ COMMITTED | READ UNCOMMITTED }; Una vez realizada la primera consulta, ya no se puede cambiar el nivel de aislamiento de la transacci on. Read commited Es el nivel de aislamiento por defecto en PostgreSQL. Cuando una transacci on utiliza este nivel, un SELECT solo ve data enviada antes de que la consulta empiece, nunca ve data no enviada (uncommitted) o cambios enviados por transacciones concurrentes durante la ejecuci on de la consulta. Sin embargo, SELECT si ve los cambios efectuados dentro de la transacci on as no hayan sido a un enviados. Adem as, cada SELECT ve datos diferentes si otra transacci on ha cambiado los datos antes de que empiece a ejecutarse, por lo que diferentes SELECT dentro de una misma transacci on pueden ver diferente data en la BD. Por ejemplo, en una sesi on A ejecutar los siguientes comandos sobre una tabla existente.

BEGIN; SET TRANSACTION ISOLATION LEVEL READ COMMITTED; SELECT * FROM tabla_ejemplo; Luego en una sesi on B ejecutar:

27

UPDATE tabla_ejemplo SET .... WHERE ...; En la sesi on A volver a ejecutar un SELECT y terminar la transacci on:

SELECT * FROM tabla_ejemplo; END; Se puede observar que los dos select en la misma transacci on devolvieron resultados diferentes. Los comandos de escritura (UPDATE, DELETE, SELECT FOR UPDATE y SELECT FOR SHARE) se comportan igual que SELECT al buscar registros: solo van a encontrar los registros que ya estaban enviados (committed) al empezar el comando. Si el registro ha sido modicado despu es de que empez o el comando, el comando va a esperar a que los cambios se env en o se descarten. Si los cambios de la transacci on anterior se env an, la segunda transacci on va a ignorar el registro si ha sido eliminado por la primera o va a tomar en cuenta los cambios si ha sido modicado, reevaluando la condici on de b usqueda (WHERE) para comprobar si se sigue aplicando. Por ejemplo, abrir una sesi on A y ejecutar:

BEGIN: SET TRANSACTION ISOLATION LEVEL READ COMMITTED; UPDATE tabla_ejemplo SET .... WHERE ...; En otra sesi on B ejecutar:

BEGIN: SET TRANSACTION ISOLATION LEVEL READ COMMITTED; UPDATE tabla_ejemplo SET .... WHERE ...; Mientras la primera transacci on no termine, la segunda transacci on se quedar a esperando el resultado. Debido a lo explicado, el modo Read committed puede llevar a ver una instant anea inconsistente de la BD: puede ver los efectos de actualizaciones concurrentes en las registros que est a procurando actualizar pero no ve los efectos de estos comando en otros registros de la BD. Usos complejos de la Bd pueden producir resultados indeseados en el modo Read Committed, por ejemplo un comando DELETE que opere en data que ha sido agregada y removida de su criterio de b usqueda por otro comando, como en la siguiente transacci on.

BEGIN; UPDATE website SET hits = hits + 1; -- Execute in other sesion: DELETE FROM website WHERE hits = 10;

28

COMMIT; Los valores que tengan 10 antes o despu es de la actualizaci on no van a ser afectados, ya que los que tienen 9 antes de la actualizaci on siguen siendo vistos como 9 por el DELETE concurrente y los que tienen 10 est an siendo modicados por la primera transacci on por lo que el DELETE debe esperar a que termine la actualizaci on y en ese momento su valor ser a de 11. Es debido a esta caracter stica que Read Committed no es adecuado para todos los casos.1 Repeatable Read Este nivel solo ve ve data enviada antes de que la transacci on haya empezado, nunca ve data no enviada o enviada despu es de que la transacci on haya empezado. Si embargo la transacci on si ve los cambios enviados dentro de si aunque a un no hayan sido enviados. Este nivel de aislamiento previene todos los comportamientos mencionados en la tabla anterior.2 En este nivel, los SELECT dentro de una transacci on ven todos la misma data en la BD, data anterior a que la transacci on empezara a ejecutarse. Por ejemplo, llevar a cabo la misma prueba con el SELECT que con Read commited, pero deniendo Repeatable Read como nivel de aislamiento utilizando:

SET TRANSACTION ISOLATION LEVEL REPEATABLE READ; Los comandos que actualizan data (UPDATE, DELETE, SELECT FOR UPDATE y SELECT FOR SHARE) tienen el mismo comportamiento del SELECT al buscar registros pero en caso de que un registro este siendo modicado por una transacci on concurrente van a esperar que acabe y si el registro ha sido modicado, no se va a poder llevar a cabo la operaci on y toda la transacci on va a ser cancelada con el siguiente mensaje: ERROR: could not serialize access due to concurrent update Cuando una aplicaci on recibe este mensaje de error debe cancelar la actual transacci on y volverla a empezar de cero. Esta segunda vez la transacci on vera las actualizaciones llevadas a cabo en los registros por las otras transacciones. Este nivel de aislamiento provee una rigurosa garant a de que cada transacci on ver a una imagen estable de la BD dentro de si. A un as , este nivel puede tener problemas debido a transacciones concurrentes que provoquen continuas cancelaciones de una transacci on. Serializable Este nivel provee el aislamiento m as estricto para las transacciones. Este nivel emula ejecuci on serial de las transacciones, como si hubieran sido ejecutadas una despu es de la otra, de forma serial en vez de concurrente. A un as , las aplicaciones deben estar listas para cancelar transacciones debido a
1 2

[2] pp. 342 [2] pp. 343

29

fallas en la serializaci on. Este nivel trabaja igual que Repeatable Read a excepci on de que monitorea las condiciones que pueden hacer que un conjunto serializable de transacciones concurrentes se comporte de manera inconsistente con todas las posibles ejecuciones seriales de estas transacciones. Para garantizar la serializaci on PostgreSQL utiliza predicate locking o bloqueo por predicados, el cual consiste en analizar las transacciones para vericar si el orden de ejecuci on es consistente con el resultado. Por ejemplo, dada la tabla mytab:

Class Value 1 1 2 2 Tenemos dos transacciones, la transacci on A es: 10 20 100 200

INSERT INTO t VALUES (2, (SELECT SUM(value) FROM mytab WHERE class = 1)); Y luego inserta el resultado (30) en el campo value de un nuevo registro cuyo campo class = 2. Concurrentemente, la transacci on B es:

INSERT INTO t VALUES (1, (SELECT SUM(value) FROM mytab WHERE class = 2)); Y obtiene el resultado 300 el cual inserta en un registro cuyo campo class = 1. Luego ambas transacciones hacen commit, como no hay un orden serial de ejecuci on consistente con el resultado, el modo Serializado va a permitir a una transacci on enviar su data a la BD y la otra va a ser cancelada con el mensaje: ERROR: could not serialize access due to read/write dependencies among transactions Esto se debe a que si A se ejecuta antes de B, B hubiera obtenido un resultado de 330 no 300 y al rev es hubiera resultado en A con el valor de 330 como resultado. El bloqueo por predicados en PostgreSQL, est a basado en la data accedida por la transacci on. La garant a de que un conjunto de transacciones concurrentes serializables va a tener el mismo efecto que si se ejecutaran una tras otra, signica que si se puede demostrar que cada transacci on por separado va a tener el resultado esperado al ejecutarse, se puede tener conanza de que va a hacerlo bien en un conjunto de transacciones a un sin informaci on sobre lo que el resto de transacciones va a hacer.

30

3.3.

Descripci on del Control de Concurrencia

Al crear o modicar un registro, el nuevo registro as creado guarda el ID de la transacci on en un campo llamado XID tambi en llamado xmin, el m nimo XID capaz de ver este trozo de informaci on una vez ha sido enviado. Cuando una consulta es ejecutada utiliza el ID de la actual transacci on como un l mite para lo que puede considerarse visible. Los registros cuyo xmin es menor que el ID de la transacci on y han sido enviados son considerados para ser mostrados en la consulta. Un mecanismo similar gestiona la eliminaci on. Cada registro tiene un XID de eliminaci on, tambi en llamado el xmax, que empieza vac o para indicar que el registro no ha sido borrado. Cuando se borra un registro, el ID de la actual transacci on se convierte en su xmax , para indicar que no va a ser m as visible despu es de ese punto en el tiempo (o mejor dicho en el hist orico de transacciones). Al ejecutarse una consulta, solo incluye un registro con xmax si este es anterior al XID de la consulta. Xmin y xmax son en esencia el tiempo de vida visible del registro en t erminos de Ids. El registro solo es visible desde una consulta cuyo XID este entre ambos. El registro original va a ser eliminado despu es de un tiempo por VACUUM, el m odulo de PostgreSQL que elimina peri odicamente los registros que ya no van a ser utilizados. [5] Para ver los ids en funcionamiento se puede utilizar la funci on txid current snapshot().

3.4.

Diferencias entre MVCC y Bloqueo

PostgreSQL provee varios modos de bloqueo para para controlar el acceso concurrente a la data en las tablas. En general todas las consultas llevan a cabo alguna forma de bloqueo sobre la data a la que acceden. Un bloqueo es ejecutado por un comando como SELECT o UPDATE para tener acceso a la data con la que est an trabajando, en cambio MVCC es un modelo de trabajo del gestor de base de datos para permitir que varias transacciones al mismo tiempo (concurrencia) puedan acceder a la misma data en la BD. La principal ventaja de utilizar el modelo MVCC sobre bloqueo es que los bloqeuos de MVCC para escribir data no entran en conicto con los bloqueos para leer data. PostgreSQL mantiene la garant a de que no va a necesitar bloquear ambos a un al proveer los m as estrictos niveles de aislamiento de la transacci on. Bloqueo a nivel de tablas y registro est a disponible en PostgreSQL para aplicaciones que generalmente no necesitan aislar completamente las transacciones y preeren manejar gestionar explicitamente los puntos de conicto.

31

3.5.
3.5.1.

Ejemplo MVCC
UPDATES

Si dos sesiones al mismo tiempo procuran alterar un registro una de las dos esperar a hasta que la otra termine. Una vez que la primera sesi on termina, dependiendo de la conguraci on del servidor se toma una decisi on. Una conguraci on es el modo por defecto Read Committed, en el cual la existencia de otra sesi on que modica el mismo registro solo provoca que se verique si las condiciones para cambiar el registro a un existen en el registro cambiado por la primera transacci on, si ese es el caso se procede con el cambio, caso contrario la segunda transacci on no afecta al registro. El otro modo de conguraci on es la Serializaci on. Si otra sesi on intenta modicar un registro que ya est a siendo modicado espera a que termine la primera transacci on, si la transacci on original se termina, la segunda transacci on no puede modicar el registro y aparece un error: ERROR: could not serialize access due to concurrent updates Y la sesi on no tiene otra opci on que eliminar la transacci on en curso. Este modo se utiliza cuando se requiere que la sesi on opere con una vista id entica de la BD. Para probar cr eese una tabla y un registro en la BD: 1. $ psql -d Bd prueba 2. CREATE TABLE t (s SERIAL, i INTEGER); 3. INSERT into t(i) values (0) 4. Para ver los valores xmin y xmax SELECT xmin,xmax from t; 5. Para ver el id de la actual transacci on. SELECT txid current(); Luego desde otra sesi on in ciese una transacci on mediante Begin y actual cese el registro pero no se env e (commit) a un. 1. Para iniciar la transacci on. Begin; 2. Para ver el id de la ctual transacci on select txid current(); 3. Actualizar el registro 4. UPDATE t SET i=100 WHERE s=1; Desde la perspectiva de la segunda sesi on el registro se ha actualizado, pero si hacemos un select en la primera sesi on, no se va a ver el cambio hecho en la segunda hasta que sea enviado. 32

3.5.2.

DELETE

Al eliminar un registro hay algunas diferencias con modicarlo. Al eliminar un registro, este no se puede ir hasta que toda sesi on que lo pueda necesitar haya terminado. Al eliminar un registro, este no cambia el registro en si, sino su informaci on de visibilidad para que ya no sea visible por otras sesiones.

33

Ejercicios: 1. Crear una tabla llamada tabla transacciones. 2. Crear tres registros en la tabla. 3. Abrir dos sesiones con el mismo usuario. 4. Crear una transacci on en cada sesi on, ambas deben actualizar el mismo registro. Observar el resultado. 5. Crear otras dos transacciones, una debe eliminar un registro y la otra actualizarlo. 6. Crear dos transacciones de tipo SERIALIZABLE, en una agregar un registro y en la otra eliminar un registro (diferentes). 7. Crear dos transacciones de tipo REPEATABLE READ, en ambas eliminar diferentes registros. 8. Crear dos transacciones, una de tipo REPEATABLE READ y la otra con el nivel por defecto. La primera debe leer una tabla y la segunda debe insertar registro en esa tabla.

34

Cap tulo 4 Ajustes de rendimiento


PostgreSQL es una gran plataforma sobre la cual desarrollar aplicaciones y soluciones empresariales, pero optimizar el rendimiento no ha sido una tarea f acil. Se necesitan adecuadas reglas emp ricas para comenzar as como supervisi on y mantenimiento para mantener el sistema ejecut andose sin problemas y con el rendimiento esperado. En general para ajustar el rendimiento de una Base de Datos en PostgreSQL se siguen los siguientes pasos: Seleccionar el hardware donde ejecutar la BD, idealmente se debe probar el hardware para estar seguro de que su rendimiento es el esperado. Congurar toda la implementaci on del hardware y software de disco: nivel RAID, sistema de archivos. Optimizar la conguraci on del Servidor. Supervisar el rendimiento del servidor y cu an bien se est an ejecutando las consultas. Mejorar las consultas para que se ejecuten de forma m as eciente y agregar ndices para acelerarlas. Introducir pool de conexiones y cache. Replicar la data en m ultiples servidores y distribuir las lecturas entre todos. Partir grandes tablas en secciones, eventualmente, las m as grandes pueden ser divididas entre varios servidores.

4.1.

Conguraci on de Hardware

Una raz on importante para utilizar un gestor de c odigo abierto como PostgreSQL es que cada d olar ahorrado en el software se puede invertir en hardware. Los tres principales componentes a considerar en el presupuesto son CPU, memoria y discos.

35

4.1.1.

CPU

Actualmente los CPUs tienen dos o m as n ucleos, lo cu al lleva a los desarrolladores a preguntar dos cuestiones esenciales: 1. Qu e familia de procesadores es mejor? 2. Qu e es mejor?, m as n ucleos o n ucleos m as r apidos? En general se considera que Intel produce n ucleos m as r apidos y AMD provee m as n ucleos por d olar y sobre todo sus servidores tienen capacidad para tener mayor cantidad de n ucleos que los de la competencia. Para saber si se requieren m as n ucleos o m as r apidos es necesario supervisar los procesos existentes en el sistema. Si hay pocos procesos utilizando cada uno un CPU, entonces el servidor se beneciaria en tener n ucleos m as r apidos, esto tiende a pasar cuando se tienen procesos batch donde se procesan grandes cantidades de data. Pero si est an activos todos los CPUs con muchos procesos concurrentes, entonces el sistema mejorar a su rendimiento utilizando m as n ucleos, lo c ual es com un en aplicaciones con gran cantidad de usuarios accediendo a la BD. Otra situaci on donde es u til tener n ucleos m as veloces es al exportar o importar grandes cantidades de datos de la BD, proceso en el c ual el cuello de botella puede ser la CPU.

4.1.2.

Memoria

Cuanta memoria es necesaria para para una aplicaci on depende del tama no de la data de trabajo con el cual se ejecutan el com un de operaciones. Generalmente agregar RAM mejora el rendimiento pero hay casos en los que no: Si el conjunto de data es suciente para entrar en la RAM existente, m as RAM no va a producir grandes benecios, mejor rendimiento se va a obtener agregando procesadores m as veloces. Cuando la data es tan grande que no puede entrar en cantidad de memoria alguna, por lo que es m as u til aumentar la velocidad de los discos. Aumentar la memoria ayuda as no toda la data entre, ya que el cach e aumenta y por lo tanto los bloques m as utilizados van a permanecer en memoria, aumentado as el rendimiento.

4.1.3.

Discos

Los discos SAS son m as conables y r apidos que los SATA. Los discos enterprise SATA son mejores para RAID ya que informan r apidamente de los errores y el controlador RAID reconstruye la data errada. Los discos SAS en cambio procuran arreglar por si mismos el problema, ralentizando el arreglo de discos. Es buena pr actica poner en producci on solo discos que tengan tiempo en el mercado de tal manera que sus fallas ya hayan sido reportadas y corregidas. Los discos de estado s olido son m as veloces que los discos magn eticos tradicionales, sobre todo al buscar informaci on, pero a un no tienen la capacidad de almacenamiento de los discos magn eticos y son considerablemente m as caros. 36

4.2.

Conguraci on del S.O.

La conguraci on del Sistema Operativo para soportar una base de datos PostgreSQL incluye el sistema de archivos y los par ametros de disco.

4.2.1.

Hdparm

En el caso de los *nix, para hacer m as seguro el sistema para una Base de Datos, se debe inhabilitar el cache de escritura mediante el comando: sudo hdparm -W 0 /dev/sda

4.2.2.

Sistemas de archivos

La escritura en sistemas de archivos tienen dos componentes principales: Los bloques de datos que se escriben en el disco. La metadata del sistema de archivos. Al agregar un bloque de data en un archivo existente, se llevan a cabo las siguientes operaciones: Agregar la informaci on del nuevo bloque a la metadata de espacio de disco utilizado. Escribir el bloque de data. Escribir la metadata del archivo referenciando el uso del nuevo bloque. En caso de que se caiga el sistema a mitad de la operaci on, no se va a sobrescribir el nuevo bloque debido a que desde un inicio fue tomado en cuenta como un bloque utilizado.

4.2.3.

Journaling

La forma actual de trabajar de los sistemas de archivos es mediante journaling, t ecnica por la cual se escribe el inicio y n de cada escritura en el journal, se escribe la metadata del sistema de archivos y del archivo, el bloque de datos y su utilizaci on. El journaling es algo pesado debido a que por cada operaci on en disco se debe escribir varias veces en el journal. Este se lleva a a cabo de la siguiente manera: Escribe la metadata del inicio de la transacci on en el journal. Escribe la metadata del cambio de espacio utilizado en el journal. Escribe el cambio en el bloque de datos en el journal. Escribe el cambio en la metadata del archivo en el journal. Agregar el bloque de data a la metadata de la lista de espacio utilizado. Escribe el bloque de data. Escribe metadata del archivo referenciando el uso del bloque. 37

Escribe la metadata del n de la transacci on en el journal. Con estas operaciones se obtiene la habilidad de recuperar el sistema de cualquier caida. Si no se llega a terminar una transacci on de escritura el sistema de archivos puede ignorar o deshacer cualquier trabajo parcial hecho hasta el momento. Este enfoque hace que sea pesado utilizar el journaling completo con una base de datos, ya que toda transacci on es escrita cuatro veces. Para evitar la sobrecarga de trabajo, con la base de datos se utiliza solo journaling de la metadata, ya que PostgreSQL se encarga de la integridad de su data.

4.2.4.
Ext

Sistemas de archivos de Linux

Las versiones modernas de Ext (3 y 4) tienen tres niveles de journaling, que se denen como opciones al montarse el sistema de archivos: data=writeback : Los cambios en la data no son guardados en el journal, solo los cambios en la metadata, pero el orden en que son guardados relativo a los bloques de data no es garantizado. Despu es de una caida de sistema, los archivos pueden quedar con basura al nal por escrituras incompletas y se puede tener una mezcla de data vieja y nueva sobre los archivos. data=ordered : La metadata es guardada en el journal pero no los cambios en la data, pero en todos los casos la metadata es escrita solo despu es de que los bloques de data hayan sido escritos. Despu es de una ca da del sistema, no van a haber archivos de tama nos incorrectos. data=journal : Journaling completo Los cambios en la data y la metadata son escritos en el journal antes de que el sistema de archivos sea tocado. Debido a que realiza su propio chequeo de la integridad de los datos, en PostgreSQL no es necesario utilizar journaling completo, por lo que la opci on ordered va a permitir mayores velocidades. El tama no m aximo para las particiones es de 16TB y para los archivos es de 2TB en ext3, l mite que busca ser superado por ext4. XFS XFS es m as veloz que los ext debido a que fue dise nado para ser eciente en el journaling, pero solo registra los cambios de la metadata en el journal, por lo que se parece al modo writeback de ext3 y es considerado inseguro. Para superar este problema se debe colocar: full page writes = on en postgresql.conf. XFS tiene la ventaja de que es m as eciente al ser utilizado con RAID y adem as puede soportar archivos de m as de un mill on de TB, muy superior a los sistemas de archivos ext.

4.2.5.

Conguraci on del sistema de archivos en Linux

Sin importar el sistema de archivos que se utilice, existen conguraciones que pueden mejorar su rendimiento. 38

Read ahead El primer par ametro a congurar en Linux es el read-ahead de los dispositivos de almacenamiento. Cuando se hacen lecturas secuenciales que se mueven hacia adelante, esta funcionalidad hace que el Sistema Operativo solicite los bloques del disco antes de que la aplicaci on los solicite, ahorrando as mucho tiempo. Para ver el estado actual de read-ahead se ejecuta el comando: $ blockdev getra /dev/sda Para mejorar este par ametro se le aumenta a un valor entre 4096 y16384 mediante el siguiente comando: $ blockdev setra 4096 /dev/sda Tiempo de acceso a los archivos (File access times) Cada vez que se accede a un archivo en Linux, se actualiza un atributo del archivo llamado el tiempo del u ltimo acceso (atime). Esta sobrecarga se vuelve grande cuando se hacen muchas lecturas de un archivo, lo cu al no es deseable. Se puede eliminar este comportamiento agregando el par ametro noatime a las opciones de montaje en /etc/fstab. /dev/sda1 ext3 noatime,errors=remount-ro 0 1 Cache de lectura e intercambio de p aginas Linux procura utilizar todo espacio extra de RAM para poner en cache el sistema de archivos, al igual que PostgreSQL, compitiendo ambos por el recurso. Cuando el sistema tiene poca RAM, debe optar por reducir el tama no del cache o incrementar el intercambio de p aginas con el disco (swapping). Este comportamiento est controlado por el par ametro swappiness del kernel. Para ver el valor actual del par ametro, se accede a /proc/sys/vm/swappiness mediante el comando: sudo less /proc/sys/vm/swappiness Y la forma m as f acil de ajustarlo es agregar la siguiente l nea en /etc/sysctl.conf: vm.swappiness=0 El valor de 0 disminuye el tam no del cache del S.O en vez de aumentar el swapping, lo cual redunda en un incremento de la perfomance en la mayor a de casos. Otro par ametro relacionado es el que controla la tendencia de Linux a permitir que los procesos separen m as memoria de la que necesitan, la cu al se puede desactivar mediante el par ametro en /etc/sysctl.conf: vm.overcommit memory=2

39

4.2.6.

BSD

Los sistemas BSD, en especial FreeBSD han sido conocidos por su alta calidad, sobre todo en la implementaci on de servidores. Entre los sistemas de archivos de FreeBSD, ZFS es el m as utilizado. ZFS En ZFS, por defecto se utilizan registros de 128KB de tama no, lo cu al es u til cuando se leen grandes cantidades de informaci on pero ineciente cuando las lecturas son m as peque nas y al azar. En caso de que las lecturas sean de peque nas cantidades de informaci on al azar, se recomienda reducir el tama no del registro de ZFS para igualarlo al de PostgreSQL de 8KB. Para llevarlo a cabo se utiliza el siguiente comando: $ zfs set recordsize=8K zp1data Esta conguraci on se debe hacer antes de crear ninguna Bd en el dispositivo de almacenamiento. ZFS tiene funcionalidades que lo hacen muy apto para las bases de datos como implementar sumas de comprobaci on en toda lectura y escritura de bloques de datos y mayor velocidad para copiar grandes cantidades de informaci on.

4.3.

Memoria para el cache de la Base de Datos

Cuando se inicia un servidor PostgreSQL, este reserva una cantidad ja de bloques de memoria. Adicionalmente todo cliente que se conecta utiliza una cantidad de memoria, aumentandola a medida que el cliente utiliza recursos y realiza operaciones como ordenamientos y guarda data de transacciones en espera del commit. Algunos par ametros de la base de datos pueden ser denidos por los clientes a medida que se conectan. Por ejemplo, el par ametro work mem limita la cantidad de memoria que puede ser utilizada para ordenamiento y puede ser incrementado por el cliente luego de conectarse, utilizando memoria no ocupada por otros procesos. El mayor componente de la memoria compartida es la cache, la que se dene por un par ametro llamado shared buers. Monitorear y optimizar como se usa esta memoria es el objetivo de la presente secci on.

4.3.1.

Unidades de memoria en postgresql.conf

Para indicar la memoria que se quiere asignar a un par ametro hay que especicar la unidad de memoria, por ejemplo, si se desea especicar el tama no del par ametro wal buers que controla cuanta memoria utiliza usar para el buer del WAL, se escribe lo siguiente en postgresql.conf: wal buers = 64 KB La base de datos internamente convierte el valor en sus propias unidades internas, que para este par ametro son bloques de 8K.

40

La vista pg settings de la base de datos sirve para ver las conguraciones y la funci on current setting() puede ser usada para mostrar informaci on sobre los par ametros, al igual que SHOW, pero adem as puede ser utilizada en una consulta. Por ejemplo:

show wal_buffers; SELECT name,setting,unit,current_setting(name) FROM pg_settings WHERE name=wal_buffers;

4.3.2.

Cache de la Base de Datos

El cache de la base de datos es el espacio de memoria donde PostgreSQL almacena los resultados de las consultas m as utilizadas, de tal manera que pueda responder con mayor velocidad a las nuevas consultas que se presenten. Como regla general se puede establecer que darle un 25 % de la memoria RAM del sistema al par ameumero razonable para el cache de la base de datos. tro shared buers es un n En caso de que la memoria RAM supere los 8GB de y la versi on de PostgreSQL en ejecuci on sea una de 32 bits, no se aconseja incrementar shared buers sobre los 2GB debido a que se puede sin memoria virtual. Se puede explorar el cache de la Base de Datos utilizando el m odulo pg buercache, uno de los de m odulos contrib disponibles con PostgreSQL. En un servidor de producci on no es vital pero sirve para aprender como funciona la base de datos con su memoria compartida con el n de aprender a optimizarlo.

4.4.

Conguraci on (postgresql.conf )

Las principales opciones de conguraci on de PostgreSQL est an en el archivo postgresql.conf. Al cambiar las conguraciones se puede requerir reiniciar el servidor o recargar el archivo de conguraci on. Cada par ametro de conguraci on tiene un contexto asociado donde puede ser cambiado. Para saber cu al es, se consulta a la base de datos, por ejemplo:

select name,context from pg_settings; Los contextos son los siguientes: internal: Son par ametros sobre todo internos establecidos en tiempo de compilaci on. No pueden ser cambiados sin recompilar el servidor. postmaster Solo se actualizan reiniciando el servidor. Todos los par ametros referidos a memoria son de este tipo. 41

sighup: Enviar al servidor una se nal HUP va a causar que recargue postgresql.conf y todos los cambios hechos a estos par ametros estar an inmediatamente activos. backend: Estos par ametros son similares a los de sighup excepto que los cambios hechos no van a afectar a las sesiones ejecutandose. superuser: Pueden ser modicados por cualquier superusuario en cualquier momento y se activan sin recargar. La mayor a de par ametros en este esquema se reeren a la conguraci on de los logs del sistema. user: Las sesiones individuales pueden ajustar estos par ametros en todo momento. Sus cambios solo impactar an en la sesi on. La mayor a de estos par ametros alteran como se ejecutan las consultas. Para reiniciar el servidor se debe reiniciar el servicio, lo cu al var a en cada S.O. En ubuntu y otros S.O de la familia debian se utiliza el siguiente comando: sudo /etc/init.d/postgresql restart Para recargar el archivo postgresql.conf en el servidor, es necesario conectarse como superusuario y ejecutar la funci on pg reload conf: postgres=# SELECT pg reload conf(); Se puede tambi en enviar una se nal HUP utilizando el comando kill. ps -eaf grep postgres -D $ kill -HUP 11185 El anterior comando envia la se nal HUP al servidor postgresql de id 11185.

4.4.1.

postgresql.conf

Algunos de los par ametros m as importantes son: listen addresses: Indica a PostgreSQL que ips escuchar, por defecto es localhost pero se puede indicar una lista de ips o * para indicar todas. Port: Por defecto es 5432 pero puede ser cambiado por otro. max connections: Es el m aximo numero de conexiones permitidas. Como cada conexi on utiliza una peque na cantidad de memoria, es posible para sistemas con poca memoria no permitir tantas conexiones. Es importante no establecer este par ametro muy por encima de lo que se necesita. Se desperdicia memoria compartida, lo cu al es muy oneroso en caso de que sea peque na. shared buers: dene la cantidad de memoria que se comparte a trav es de todas las conexiones para guardar las p aginas recientemente accedidas. Tiene efecto sobre todo en la perfomance de las consultas. Es deseable que este a un valor alto, por lo menos un 25 % de la memoria.

42

eective cache size: Es un estimado de cuanta memoria se espera este disponible en los caches del SO y PostgreSQL. Es utilizado por el planicador de consultas para deducir si los planes considerados entrar an en la RAM o no. Si se tiene un servidor dedicado este valor debe ser un 50 % de la RAM. work mem: Controla la cantidad m axima de memoria asignada a cada operaci on como ordenamiento, joins, etc. La cantidad o ptima de memoria depende del tipo de trabajo que se lleve a cabo, la cantidad de memoria de la que se disponga entre otros. Si el tipo de trabajo es ligero entonces este valor debe ser bajo, caso contrario debe ser m as alto. Es una de las maneras m as efectivas de incrementar la velocidad del servidor. La forma gen erica de asignarlo es considerar cuanto RAM hay fuera de shared buers dividida entre max connections y tomar un porcentaje del resultado, la mitad ser a una cantidad elevada. maintenance work mem: Es el total de memoria asignada para labores de mantenimiento. Aproximadamente cada proceso de mantenimiento (VACUUM, CREATE INDEX, ALTER TABLE ADD FOREIGN KEY) no necesita m as de del 5 % de la RAM, lo que es 50MB por cada GB de memoria. wal buers: El valor por defecto es de 64KB, lo cu al es muy bajo para los tama nos actuales de la RAM, por lo que incrementarlo a 16MB es normal actualmente. eective cache size: Al hacer operaciones que requieren gran uso de memoria, la base de datos compara su tama no con el de todos los caches reunidos (propio y del Sistema operativo). Este par ametro no reserva memoria, solo sirve para que la Base de datos compare el tama no de las operaciones a realizar para decidir el curso de acci on. En UNIX se calacula sumando los valores de free y cached que se ven en los comandos free o top y sumando adem as el valor de shared buers.

4.4.2.

Conguraci on de logs

La generaci on de Logs es importante debido a que permite conocer las acciones de la BD y los usuarios. Dependiendo del nivel de Logs, se va a generar mayor o menor cantidad de informaci on que permitir a conocer las acciones de la Bd y sus usuarios en un periodo determinado de tiempo. El archivo de logs generalmente est a en /var/log en los sistemas basados en Unix. La conguraci on de los logs se realiza en postgresql.conf (generalmente localizado en /etc/postgresql en m aquinas *nix). Las conguraciones por defecto de logs en postgresql.conf son las siguientes: La opci on de conguraci on log destination dirige los errores hacia la salida est andar, se pueden redirigir hacia un archivo utilizando pg ctl -l al iniciar el servidor. log destination = stderr: El par ametro logging collector si se pone en o signica que no se quiere recoger la salida de errores est andar para escribirla en otro sitio. Si se pone en on se crea un archivo de logs por d a. logging collector = o El par ametro log line prex se puede congurar para agregar datos al inicio de toda l nea del log. Si est a vac o no se agrega nada. 43

log line prex = El par ametro log directory indica el directorio donde se crean los logs. log directory = pg log Y log lename es el formato del nombre de los archivos de logs de Postgresql, utilizando fecha y hora. log lename = postgresql- %Y- %m- %d %H %M %S.log El sistema operativo no se encarga del mantenimiento de los logs, por lo que el administrador del sistema ser a el responsable de hacerlo, de preferencia utilizando alg un m etodo autom atico como un script. Detalle de cada par ametro de conguraci on: log line prex Este par ametro de conguraci on est a vac o por defecto, se le pueden a nadir par ametros para que se agreguen al inicio de cada l nea del log. %t: Timestamp %u: Database user name %r: Remote host connection is from %d: Database connection is to %p: Process ID of connection Aunque al inicio no se sepa porque se desean estos valores, son muy u tiles para rastrear comportamientos. Para hacer los logs de postgreSQL compatibles con pgFouine (una herramienta para analizar logs) se puede utilizar alguna de estas l neas. log line prex = %t [ %p]: [ %l-1] log line prex = %t [ %p]: [ %l-1] user= %u,db= %d log line prex = %t [ %p]: [ %l-1] user= %u,db= %d,remote= %r log statement Para decidir el detalle del log que se va a guardar se utiliza el par ametro de conguraci on log statement. None: ning un log ddl: Solo data denition language como create y drop. Mod: Registra todas las acciones que implican cambio de un valor, lo cu al en la pr actica es todo menos las consultas SELECT. All: Toda acci on, es en general impr actico ya que genera un crecimiento muy r apido del tama no del log (he tenido logs que en d as alcanzaron los 20GB).

44

log min duration statement En caso se desee solo registrar transacciones que est en durando m as de lo esperado, se puede utilizar la opci on de conguraci on log min duration statement para registrar solo registrar las acciones que duren m as de una cantidad de tiempo medido en milisegundos. Por ejemplo, log min duration statement=1000 signica que se registrar an las acciones que duren m as de un segundo, muy u til para ubicar problemas de perfomance. Logs en CSV Un formato reciente (presente desde postgreSQL 8.3) son los logs guardados como archicos csv. Este tipo de logs permiten que se puedan analizar con diversas herramientas e incluso importarlos en la misma BD para llevar a cabo su an alisis mediante consultas SQL. Para activar esta funcionalidad, se debe ajustar el destino de los logs y poner en on el colector. log destination = csvlog logging collector = on Luego de efectuar los cambios, se debe reiniciar el servidor y de ah en adelante los logs se guardaran en archivos .csv en vez de .log. Una vez generado un log en csv, secrea la tabla postgres log con la estructura del csv:

CREATE TABLE postgres_log ( log_time timestamp(3) with time zone, user_name text, database_name text, process_id integer, connection_from text, session_id text, session_line_num bigint, command_tag text, session_start_time timestamp with time zone, virtual_transaction_id text, transaction_id bigint, error_severity text, sql_state_code text, message text, detail text, 45

hint text, internal_query text, internal_query_pos integer, context text, query text, query_pos integer, location text, application_name text, PRIMARY KEY (session_id, session_line_num) ); Y se importa a la Bd mediante:

COPY postgres_log FROM /home/postgres/data/pg_log/postgresql-2010-03-28_215404.csv WITH CSV; Una vez importado se pueden ejecutar queries que lo analicen, como por ejemplo:

SELECT min(log_time),max(log_time) FROM postgres_log WHERE command_tag=COMMIT; Comando sql que muestra el primer y u ltimo commit enviado a la BD. An alisis de Logs Una vez se tienen los logs se necesita analizarlos para conocer la perfomance de nuestra BD. pg stat statements: Es un m odulo contrib que se instala utilizando:

CREATE EXTENSION pg_stat_statements; Y se habilita congurando el siguiente par ametro en postgresql.conf. shared preload libraries = pg stat statements Luego de reiniciar el servidor y ejecutar consultas, la vista pg stat statements se va a llenar con informaci on la cu al puede ser consultada como cualquier otra vista. SELECT total_time, query FROM pg_stat_statements ORDER BY total_time DESC;

46

4.5.

Conguraci on de un nuevo servidor

La optimizaci on inicial de un servidor puede ser un proceso mec anico: Ajustar los logs para ser m as verbosos. Utilizar un 25 % para shared buers. Estimar generosamente el m aximo n umero de conexiones, ya que a partir de ese n umero el sistema rechazar a nuevas. Iniciar el servidor y asignar eective cache size sumando shared buers y la cache del Sistema Operativo. Calcular work mem dividiendo el cache del S.O entre max connections y luego entre dos. Establecer maintenance work mem a un valor de 50MB por cada GB de RAM. Incrementar wal buers a 16 MB.

4.5.1.

Efectos del cache de la BD

Es importante resaltar que cuando se ejecuta una consulta varias veces, las consultas posteriores van a ser m as r apidas debido a que los resultados est an en la cache de la base de datos. Para eliminar el efecto del cache al probar varias consultas con un mismo n, se debe ejecutar varias veces las consultas de tal modo que la data este en cache y as deje de impactar en la comparaci on.

4.6.

Indices

Un ndice es una lista organizada de valores que aparece en una o m as columnas de una tabla. Si se desea un subconjunto de los registros de la tabla, una consulta puede usar el ndice para determinar que las son las que busca en vez de examinar cada la. Adem as, debido a que un ndice tiene un orden, sirven para incrementar la velocidad del ordenamiento de los registros de una tabla. Los ndices ayudan a la base de datos a disminuir la cantidad de data que necesita procesar para ejecutar una consulta. Para crear un ndice en una tabla se ejecuta el siguiente comando:

CREATE INDEX i ON t(v); Donde i es el nombre del ndice y v es el campo de la tabla con el que se va a crear el ndice. Los ndices pueden ser muy grandes y su mantenimiento ser costoso en recursos para la base de datos, por lo que su creaci on debe estar justicada por importantes mejoras en la velocidad de las consultas. Mediante EXPLAIN ANALYZE se puede hallar si fue u til o no la creaci on del ndice.

47

Cuando un campo es denido como Primary Key al ser creada la tabla, autom aticamente se le crea un UNIQUE INDEX para asegurar que todos sus valores sean u nicos. Para que no se acepten valores nulos es una buena pr actica agregar NOT NULL al campo.

48

Ejercicios:

1. Determinar si su servidor necesita m as RAM. 2. Determinar si su servidor necesita m as n ucleos o n ucleos m as potentes. 3. Determinar que sistema de archivos ser a mejor para su servidor. 4. Calcular el tama no ideal de su par ametro shared buers. 5. Calcular el tama no ideal de su par ametro work mem. 6. Calcular el tama no ideal de su par ametro eective cache size. 7. Ejecute un SELECT sobre una tabla y analice su plan. 8. Haga lo mismo para un UPDATE y un INSERT.

49

Cap tulo 5 Ajustes de rendimiento II: Optimizaci on de las Bases de datos


Para algunos administradores de Bases de datos y desarrolladores, optimizar las consultas es la parte m as importante de la optimizaci on de una base de datos.

5.1.

Data de ejemplo

Para optimizar consultas, se necesita data que analizar, para lo cual se utilizar a la base de datos Dell Store 2, originalmente creata por Dell y luego portada a PostgreSQL. Se puede descargar de http://pgfoundry.org/projects/dbsamples/. $ $ $ $ $ $ wget http://pgfoundry.org/frs/download.php/543/dellstore2-normal-1.0.tar.gz tar xvfz dellstore2-normal-1.0.tar.gz cd dellstore2-normal-1.0/ sudo su postgres -ccreatedb dellstore2 sudo su postgres -c psql -f dellstore2-normal-1.0.sql -d dellstore2 sudo su postgres -c psql -d dellstore2 -c VACUUM VERBOSE ANALYZE

Para conocer el tama no de la base de datos ejecutar:

SELECT pg_size_pretty(pg_database_size(dellstore2)); Los ejemplos en este cap tulo se dar an a partir de Dell Store 2, a menos que se indique lo contrario. [5] La estructura de la data es sencilla: Hay un n umero de productos que la tiendas vende, cada uno de los cu ales entra en una categor a. La tienda tiene clientes. Los clientes dan o rdenes de compra. Cada orden tiene un n umero de l neas, cada una de las cu ales referencia productos siendo comprados. 50

Una historia de cliente es salvada listando todos los productos que el cliente alguna vez ha ordenado.

5.2.

Timing

Para conocer cuanto demora en ejecutarse una consulta se utiliza el comando timing antes de ejecutar la consulta de tal manera que mida el tiempo requerido.

dellstore2=# \timing dellstore2=# SELECT count(*) FROM customers; count ------20000 Time: 9,245 ms Para desactivar volver a escribir \timing.

5.3.

Explain y Explain Analyze

Para conocer el porque de velocidad de ejecuci on de una consulta se utiliza el comando EXPLAIN antes de la consulta lo cual muestra el resultado esperado de dicha consulta o query plan (plan de la consulta). Si se utiliza EXPLAIN ANALYZE se obtiene la estimaci on describiendo lo que espera el planicador de PostgreSQL y adem as lo que realmente sucede despu es de ejecutar la consulta. Por ejemplo, si se ejecuta:

EXPLAIN ANALYZE DELETE * FROM t; No solo se va a obtener el plan sino efectivamente se va a eliminar todo el contenido de la tabla t.

5.4.

Las consultas y la cache

Cuando la data necesaria para responder a una consulta est a en la cache de la base de datos o del sistema operativo, la consulta se lleva a cabo m as r apido debido a que ya no se necesita recuperar la data del disco, solo obtenerla de la memoria. Si se ejecuta dos veces una consulta, la segunda vez va a ejecutarse m as r apido. Cuando la consulta empieza a ejecutarse siempre con la misma duraci on, signica que su data en la cache se ha estabilizado y ya no indice en el resultado. [5]

51

5.4.1.

Efecto de la cache

Para identicar el impacto de la cache, se va a limpiar la cache del sistema y luego se volver a a ejecutar la consulta: Limpiar la cache: $ sudo /etc/init.d/postgresql stop $ sudo su # sync # echo 3 /proc/sys/vm/drop caches # exit $ sudo /etc/init.d/postgresql start Se ejecuta la consulta: $ psql -d dellstore2 \timing SELECT count(*) FROM customers; count ------20000 (1 fila)

Duracion: 350,276 ms

SELECT count(*) FROM customers; count ------20000 (1 fila) Como se puede apreciar, la cache inuencia en gran medida el rendimiento de las consultas en el sistema. Para eliminar el efecto de la cache sobre una consulta, esta debe ser ejecutada varias veces hasta que sus tiempo de ejecuci on sean similares.

5.4.2.

Estructura del plan de la consulta

La salida del comando EXPLAIN est a organizada en una serie de nodos. Cada l nea de la salida es un nodo. Al m as bajo nivel est an los nodos que analizan tablas e ndices. Los nodos de m as alto nivel cogen la salida de los nodos de bajo nivel y operan sobre esta.

52

Por ejemplo:

# EXPLAIN ANALYZE SELECT * FROM customers; QUERY PLAN

-----------------------------------------------------------------------------------------Seq Scan on customers (cost=0.00..676.00 rows=20000 width=268)

(actual time=0.010..27.434 rows=20000 loops=1) Total runtime: 52.451 ms (2 filas) Al ejecutarse con EXPLAIN ANALYZE la duraci on aumenta varias veces. En casos de querys m as complejos la sobrecarga producida por el an alisis es menor, a un as no se debe de conar completamente en los tiempo producidos por EXPLAIN ANALYZE. Este plan tiene un nodo, un nodo Seq Scan cost=0.00..676.00: El primer costo es el costo de iniciar el nodo. Esto es cuanto trabajo es estimado antes de que este nodo produzca su primera la de salida. En este caso es 0 ya que una b usqueda secuencial devuelve resultados de forma inmediata. El segundo n umero es el costo estimado de ejecutar todo el nodo hasta que termine. rows=20000: El n umero de las que este nodo espera como salida. width=268 : El n umero esperado de bytes de cada la de la salida. Los n umeros actuales muestran como realmente se llevo a cabo la consulta: actual time=0.011..34.489: El actual costo de inicio no fue cero, se necesito una peque na fracci on de tiempo para empezar. Una vez que empez o necesito 34.489 segundos para terminar. Rows=20000: Tal como se esperaba fueron 20000 las. loops=1: Algunos nodos, como los que hacen joins, se ejecutan m as de una vez. En ese caso el valor de loops va a ser m as de uno y el tiempo y la cantidad de las van a ser referidas a cada loop no al total.

5.4.3.

Costo de computaci on

La labor b asica del optimizador de consultas es generar planes que puedan utilizarse para ejecutar una consulta y escoger el que tenga el menor costo de ejecuci on. El costo es hecho de forma arbitraria. seq page cost: Cuanto demora leer una sola p agina desde el disco en forma secuencial. El resto de par ametros son relativos a este cuyo valor es 1.0. random page cost: El costo de lectura cuando los registros est an dispersos por varias p aginas. El valor por defecto es 4.0. cpu tuple cost: Cuanto cuesta procesar un solo registro, su valor por defecto 0.1.

53

cpu index tuple cost: El costo de procesar una sola entrada de un ndice. El valor por defecto es 0.005, menor de lo que cuesta procesar un registro debido a que los registros tienen mucha m as informaci on de cabecera (como xmin y xmax ). cpu operator cost: El costo esperado de procesar una funci on o un operador (la suma de dos n umeros por ejemplo) y por defecto es 0.0025. Se puede comparar en una tabla:

Par ametro seq page cost random page cost cpu tuple cost cpu index tuple cost cpu operator cost

Valor por Defecto 1.0 4.0 0.01 0.005 0.0025

Velocidad relativa Reference 4X slower 100X faster 200X faster 400X faster

Todos estos valores se pueden encontrar en postgresql.conf. Se pueden utilizar estos n umeros para calcular el costo mostrado en el ejemplo previo. Una b usqueda secuencial de la tabla customers debe leer cada p agina en la tabla y procesar cada registro. Se pueden combinar los costos internos utilizados por PostgreSQL con las estad sticas utilizadas por el optimizador.

SELECT relpages, current_setting(seq_page_cost) AS seq_page_cost, relpages * current_setting(seq_page_cost)::decimal AS page_cost, reltuples, current_setting(cpu_tuple_cost) AS cpu_tuple_cost, reltuples * current_setting(cpu_tuple_cost)::decimal AS tuple_cost FROM pg_class WHERE relname=customers; Se obtiene:

relpages | seq_page_cost | page_cost | reltuples | cpu_tuple_cost | tuple_cost ----------+---------------+-----------+-----------+----------------+-----------476 | 1 | 476 | 20000 | 0.01 | 200

54

Agregar el costo de leer la p agina (page cost ) al costo de procesar los registros (tuple cost ) y se obtiene 676, el costo mostrado por EXPLAIN. Los par ametros de costo se pueden congurar, una conguraci on com un cuando se sabe que gran parte de la base de datos puede entrar en la memoria es reducir random page cost a 2, debido a que un elevado porcentaje de las p aginas est a en la cache y es encontrada con mayor facilidad que en el disco. Para saber que columnas se est an utilizando en una consulta, se puede utilizar el modo verboso:

EXPLAIN VERBOSE SELECT * FROM customers;

5.5.

Optimizaci on de consultas

Para optimizar las consultas en primer lugar se explicar a como mejorar el rendimiento de la obtenci on de los registros y luego de las operaciones con los registros.

5.5.1.

Armando conjuntos de registros

Para optimizar la selecci on de los registros buscados por una consulta se pueden tomar en cuenta diversas optimizaciones. Id de los registros Todo registro tiene un Id, el que se puede ver en la columna ctid. Se puede utilizar en una misma transacci on para referirse a un registro que se repite varias veces y as acelerar su b usqueda. No es u til en diferentes transacciones ya que puede cambiar con una actualizaci on. Tambi en sirve para distinguir entre registros id enticos, por ejemplo al eliminar registros duplicados. Un ejemplo de ctid:

EXPLAIN SELECT customerid FROM customers WHERE ctid=(0,1);

QUERY PLAN --------------------------------------------------------Tid Scan on customers (cost=0.00..4.01 rows=1 width=4)

TID Cond: (ctid = (0,1)::tid)

Indices Cuando se ejecutan consultas que incluyen LIMIT es u til buscar mediante un campo que este indexado, ya que as el ordenamiento ser a m as r apido.

55

5.5.2.

Procesando los nodos

Una vez que se tiene un conjunto de registros, el siguiente tipo de nodo que se va a encontrar cuando se usa una sola tabla son aquellos que procesan el conjunto de varias formas. Estos nodos por lo general cogen un conjunto de registros y devuelven otro. Ordenamiento - Sort Nodos de ordenamiento aparecen cuando se utiliza ORDER BY en las consultas:

EXPLAIN ANALYZE SELECT customerid FROM customers ORDER BY zip; QUERY PLAN ----------------------------------------------------------------------Sort (cost=2104.77..2154.77 rows=20000 width=8) (actual time=74.299..101.232 rows=20000 loops=1) Sort Key: zip Sort Method: external sort -> Seq Scan on customers Disk: 352kB (cost=0.00..676.00 rows=20000 width=8)

(actual time=0.013..33.266 rows=20000 loops=1) Total runtime: 126.535 ms Las operaciones de ordenamiento se pueden ejecutar en memoria (m as r apido) o en disco (m as lento). En el ejemplo podemos ver que a pesar de la peque na cantidad de data (352kB) esta ha sido calculada en el disco. A un cuando es menor que el valor por defecto de work mem (1MB), el algoritmo quicksort (utilizado en la memoria) necesita m as memoria que la utilizada en el disco duro al combinar archivos previamente ordenados. Si el par ametro work mem es incrementado, la operaci on se lleva a cabo en memoria. [5]

SET work_mem=2MB; EXPLAIN ANALYZE SELECT customerid FROM customers ORDER BY zip; QUERY PLAN ----------------------------------------------------------------------------Sort (cost=2104.77..2154.77 rows=20000 width=8) (actual time=62.513..87.639 rows=20000 loops=1) Sort Key: zip Sort Method: quicksort -> Memory: 1294kB (cost=0.00..676.00 rows=20000 width=8)

Seq Scan on customers

(actual time=0.015..31.845 rows=20000 loops=1)

56

Total runtime: 112.588 ms Se puede apreciar que el valor por defecto no era suciente y se necesitaba aumentar work mem para que la operaci on se llevara a cabo en la memoria.

Funciones de agregaci on - Aggregate Las funciones de agregaci on reciben una serie de valores y producen una sola salida. Algunos ejmeplos son AVG(), COUNT(), EVERY(), MIN(), MAX(), STDDEV() y SUM(). Para calcular una funci on de agregaci on, se leen todos los registros y luego se pasan por por el nodo agregado para calcular el resultado:

EXPLAIN ANALYZE SELECT max(zip) FROM customers; QUERY PLAN -----------------------------------------------------------------------Aggregate (cost=726.00..726.01 rows=1 width=4)

(actual time=56.127..56.128 rows=1 loops=1) -> Seq Scan on customers (cost=0.00..676.00 rows=20000 width=4)

(actual time=0.011..26.958 rows=20000 loops=1) Total runtime: 56.203 ms No siempre este el caso, al utilizar ndices el tiempo disminuye considerablemente:

EXPLAIN ANALYZE SELECT max(customerid) FROM customers; QUERY PLAN ---------------------------------------------------------------------Result (cost=0.03..0.04 rows=1 width=0)

(actual time=0.064..0.066 rows=1 loops=1) InitPlan 1 (returns $0) -> Limit (cost=0.00..0.03 rows=1 width=4)

(actual time=0.054..0.056 rows=1 loops=1) -> Index Only Scan Backward using customers_pkey on customers (cost=0.00..534.25 rows=20000 width=4) (actual time=0.049..0.049 rows=1 loops=1) Index Cond: (customerid IS NOT NULL) Heap Fetches: 0

57

Total runtime: 0.120 ms $

5.5.3.

Joins

Las tareas m as complejas del planicador de consultas son las que tienen que ver con unir tablas entre si. Cada vez que se agrega una tabla al conjunto que se le aplicar a join, el n umero de posibilidades crece de forma dram atica. Si solo son tres tablas, el planicar considerar a todo posible plan para seleccionar el optimo, pero si son veinte tablas, la cantidad de posibilidades es muy grande para considerarlas todas. [5] En un CROSS JOIN se multiplican todos los registros de una tabla por los de otra, multiplicando de forma anidada cada registro por toda la otra tabla. En pseudoc odigo:

for each outer row: for each inner row: if join condition is true: output combined row Se puede observar algo similar en data real si es que se unen dos tablas sin un WHERE de por medio. EXPLAIN ANALYZE SELECT * FROM products,customers; QUERY PLAN -------------------------------------------------------------------------Nested Loop (cost=0.00..2500899.00 rows=200000000 width=317) (actual time=17.844..791143.955 rows=200000000 loops=1) -> Seq Scan on customers (cost=0.00..676.00 rows=20000 width=268)

(actual time=9.394..102.243 rows=20000 loops=1) -> Materialize (cost=0.00..248.00 rows=10000 width=49)

(actual time=0.002..12.694 rows=10000 loops=20000) -> Seq Scan on products (cost=0.00..198.00 rows=10000 width=49)

(actual time=8.411..25.013 rows=10000 loops=1) Total runtime: 1029182.979 ms

Bucle anidado con b usqueda mediante ndices Lo m as com un en un bucle anidado donde una tabla solo est a devolviendo un n umero limitado de registros. Si existe un ndice en una de las tablas, el optimizador lo utilizar a para limitar el n umero de registros y hacer el tiempo de ejecuci on menor.

58

Considerar el caso donde se est a buscando una sola orden utilizando un campo sin ndice (por lo que la b usqueda debe ser secuencial) pero haciendo un join con su respectiva orden de compra.

EXPLAIN ANALYZE SELECT * FROM orders,orderlines WHERE orders.totalamount=329.78 AND orders.orderid=orderlines.orderid;

QUERY PLAN ----------------------------------------------------------------------Nested Loop (cost=0.00..259.41 rows=5 width=48) (actual time=0.070..8.387 rows=9 loops=1) -> Seq Scan on orders (cost=0.00..244.00 rows=1 width=30)

(actual time=0.047..8.316 rows=1 loops=1) Filter: (totalamount = 329.78) Rows Removed by Filter: 11999 -> Index Scan using ix_orderlines_orderid on orderlines

(cost=0.00..15.36 rows=5 width=18) (actual time=0.012..0.029 rows=9 loops=1) Index Cond: (orderid = orders.orderid) Total runtime: 8.472 ms En caso de que ambas tablas utilicen un ndice la consulta es a un m as r apida:

EXPLAIN ANALYZE SELECT * FROM orders,orderlines WHERE orderlines. orderid=1000 AND orders.orderid=orderlines.orderid;

QUERY PLAN -----------------------------------------------------------------------------Nested Loop (cost=0.00..23.66 rows=5 width=48) (actual time=0.048..0.087 rows=6 loops=1) -> Index Scan using orders_pkey on orders (cost=0.00..8.27 rows=1 width=30)

(actual time=0.026..0.029 rows=1 loops=1) Index Cond: (orderid = 1000) -> Index Scan using ix_orderlines_orderid on orderlines (cost=0.00..15.34 rows=5 width=18) (actual time=0.011..0.025 rows=6 loops=1) 59

Index Cond: (orderid = 1000) Total runtime: 0.173 ms

Merge Join Este tipo de join requiere que ambas entradas esten ordenadas, luego busca a trav es de las dos en orden moviendose un registro a la vez a trav es de las tablas mientras los valores las columnas utilizadas para el join cambian. Una tabla puede ser revisada varias veces si la tabla por la que se busca tiene valores repetidos. Para ver un merge join se necesita una condici on de igualdad como la mostrada en un reporte donde se indica cuanto ha comprado cada cliente:

EXPLAIN ANALYZE SELECT C.customerid,sum(netamount) FROM customers C, orders O WHERE C.customerid=O.customerid GROUP BY C.customerid;

QUERY PLAN ----------------------------------------------------------------GroupAggregate (cost=0.03..1536.49 rows=12000 width=10)

(actual time=28.443..176.144 rows=8996 loops=1) -> Merge Join (cost=0.03..1356.49 rows=12000 width=10) (actual time=28.420..142.030 rows=12000 loops=1) Merge Cond: (c.customerid = o.customerid) -> Index Only Scan using customers_pkey on customers c (cost=0.00..484.25 rows=20000 width=4) (actual time=28.358..56.956 rows=20000 loops=1) Heap Fetches: 0 -> Index Scan using ix_order_custid on orders o (cost=0.00..672.24 rows=12000 width=10) (actual time=0.021..25.228 rows=12000 loops=1) Total runtime: 187.058 ms La consulta se realiza siguiendo los ndices de customerid tanto en customers como en orders para encajar ambas tablas entre si de forma ordenada. Luego el ejecutor puede utilizar un Merge Join de forma eciente para combinar ambos. Para optimizar esta consulta es u til no hacer el join con campos cuyas columnas tengan tablas repetidas.

60

Hash Join La principal alternativa utilizada por PostgreSQL para un Merge Join es un Hash Join. Este tipo de Join no ordena sus entradas, en vez de eso, crea una tabla Hash para cada registro de una tabla con los registros correspondientes de la otra tabla. La salida no necesariamente va a estar en orden. Una consulta para encontrar los productos que en alg un punto han sido ordenados por cualquier cliente muestra un Hash Join.

EXPLAIN ANALYZE SELECT prod_id,title FROM products p WHERE EXISTS (SELECT 1 FROM orderlines ol WHERE ol.prod_id=p.prod_id);

QUERY PLAN -----------------------------------------------------------------Hash Join (cost=1328.43..1773.80 rows=9736 width=19) (actual time=216.478..260.593 rows=9973 loops=1) Hash Cond: (p.prod_id = ol.prod_id) -> Seq Scan on products p (cost=0.00..198.00 rows=10000 width=19)

(actual time=0.008..13.163 rows=10000 loops=1) -> Hash (cost=1206.73..1206.73 rows=9736 width=4) (actual time=216.436..216.436 rows=9973 loops=1) Buckets: 1024 -> Batches: 1 Memory Usage: 234kB

HashAggregate

(cost=1109.38..1206.73 rows=9736 width=4)

(actual time=187.953..202.345 rows=9973 loops=1) -> Seq Scan on orderlines ol (cost=0.00..958.50 rows=60350 width=4) (actual time=0.008..91.152 rows=60350 loops=1) Total runtime: 272.643 ms Dependiendo del tipo de entrada puede ser mejro o peor que Merge Join. Si la entrada no est a ordenada puede ser mejor que el Merge Join. Adem as, los Hash Joins requieren memoria para guardar todos los registros, lo cu al puede requerir que se amplie el par ametro work mem. Este tipo de join es utilizado sobre todo cuando una de las tablas es peque na y construir la tabla hash es poco costoso.

5.5.4.

Ordenamiento de Joins

A medida que se incrementa el n umero de joins y la cantidad de registros, controlar la complejidad se vuelve m as importante para optimizar las consultas y el rendimiento de PostgreSQL.

61

Forzar el orden de los joins Se puede forzar a que el planicar de PostgreSQL utilice el orden de querys establecido en una consulta. Por ejemplo, una consulta que utiliza joins de forma expl cita:

SELECT * FROM cust_hist h INNER JOIN products p ON (h.prod_id=p.prod_id) INNER JOIN customers c ON (h.customerid=c.customerid); Esta consulta es igual a una realizada utilizando joins impl citos:

SELECT * FROM cust_hist h,products p,customers c WHERE h.prod_id=p.prod_ id AND h.customerid=c.customerid; En ambos casos el planicador puede elegir planes que ejecuten primero los joins entre cust hist y products o entre products y customers. En caso de que el desarrollador sepa que hay una manera eciente de hacer el join, puede indicarlo a PostgreSQL de tal forma que no pierda tiempo buscando un plan. Para hacerlo se debe reducir el par ametro join collapse limit de su valor por defecto de 8. Para impedir que se reordene la consulta, establecer el par ametro a 1. De esta forma la consulta empezar a por cust hist, seguir a por products y terminar a en customers.

SET join_collapse_limit = 1; SELECT * FROM cust_hist h INNER JOIN products p ON (h.prod_id=p.prod_id) INNER JOIN customers c ON (h.customerid=c.customerid);

Eliminar Joins Una funcionalidad de PostgreSQL es la de eliminar Joins (Left o Right) innecesarios. Por ejemplo el siguiente es un LEFT JOIN que lista productos con su inventario.

SELECT * FROM products LEFT JOIN inventory ON products.prod_id=inventory.prod_id; Pero algunas consultas no necesitan el JOIN, por ejemplo:

EXPLAIN ANALYZE SELECT products.title FROM products LEFT JOIN inventory ON products.prod_id=inventory.prod_id;

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

62

Seq Scan on products

(cost=0.00..198.00 rows=10000 width=19) (actual time=0.014..15.694 rows=10000 loops=1)

Total runtime: 28.777 ms Debido a que es un LEFT JOIN y la consulta solo busca valores de la tabla products, no es necesario el JOIN y por lo tanto PostgreSQL lo deja de lado. Debido a esta funcionalidad, si se puede utilizar LEFT O RIGHT JOIN, se deben utilizar, ya que en caso no sean necesarios, PostgreSQL los eliminar a para optimizar la consulta. Este hecho puede ser poco importante en consultas simples, pero en estructuras m as complicadas con vistas y consultas generadas autom aticamente es posible que sea una mejora signicativa. UPDATES Para realizar actualizaciones de forma o ptima, se debe especicar con claridad en la cl ausula WHERE a que registros afectar. Por ejemplo, si por alg un motivo se quisiera hacer que todos los clientes fueran de Maryland, se efectuar a la siguiente consulta:

UPDATE customers SET state=MD WHERE NOT state=MD; La condici on colocada impide la redundancia de volver a escribir donde el estado ya fuera Maryland.

5.5.5.

Tips para optimizar SQL

Para escribir consultas SQL, existen diversos consejos y reglas pr acticas que pueden ayudar a hacerlas m as ecientes. Usar expresiones simples En lo posible evitar los JOINS en favor de argumentos simples de b usqueda, por ejemplo una consulta como la siguiente: SELECT * FROM Students AS S1, Rides AS R1 WHERE S1.town = R1.town AND S1.town = Atlanta;

Puede ser simplicada a:

SELECT * FROM Students AS S1, Rides AS R1 WHERE S1.town = Atlanta

63

AND

S1.town = Atlanta;

La segunda versi on asegura que de ambas tablas se va a utilizar la menor cantidad de registros por lo que el JOIN no va a ser costoso. Asumiendo que hubieran diez estudiantes de cien que fueran para Atlanta y cinco de cien ofrecieran viajes a Atlanta, si el JOIN se ejecutara primero, se tendr an 100 * 100 = 10000 registros en el CROSS JOIN. En la segunda versi on, se tendria una tabla de diez registros y otra tabla de cinco registros para el CROSS JOIN. Otra regla pr actica es que cuando se tiene un conjunto de condiciones unidas por un AND, colocar las m as restrictivas primero. Por ejemplo:

SELECT * FROM Students WHERE sex = female AND grade = A; Esta consulta va a correr m as lento que la siguiente:

SELECT * FROM Students WHERE grade = A AND sex = female; Debido a que hay menos estudiantes con nota A que estudiantes mujeres. Otra aplicaci on del mismo concepto es un truco con predicados que involucran dos columnas para forzar la elecci on del ndice a ser utilizado. Colocar la tabla con el menor n umero de registros al nal de la cl ausula FROM y colocar la expresi on que la utiliza al inicio de la cl ausula WHERE. Por ejemplo, considerar dos tablas, una m as grande para ordenes y otra m as peque na que traduce un c odigo a ingl es, cada una con un ndice en la columna JOIN.

SELECT * FROM Orders AS O1, Codes AS C1 WHERE C1.code = O1.code; Esta consulta probablemente va a utilizar una estrategia de combinar los ndices, pero si se utiliza una expresi on sin efecto se puede forzar a PostgreSQL a utilizar el ndice de la tabla m as peque na.

64

SELECT * FROM Orders AS O1, Codes AS C1 WHERE O1.ordertype >= 00 AND C1.code = O1.code; Si se asume que todos los c odigos son mayores a 00, entonces la primera condici on siempre es cierta y se va a utilizar el ndice en Orders. El operador <> tiene algunos problemas. El optimizador puede preferir una b usqueda secuencial y no usar un ndice. Por ejemplo:

SELECT * FROM Ireland WHERE religion <> Catholic; Para romper la condici on se puede utilizar:

SELECT * FROM Ireland WHERE religion < Catholic OR religion > Catholic; Para que la segunda versi on sea m as veloz, se necesita que tenga un ndice en el campo religion. Otro truco es evitar el predicado IS NOT NULL y utilizar un valor constante m nimo en su reemplazo. Los NULLS son guardados en diferente espacio f sico que sus columnas, por lo que el motor debe hacer m as trabajo. Por ejemplo:

SELECT * FROM Sales WHERE alphacode IS NOT NULL; Puede ser escrito de man era que evite las lecturas extra:

SELECT * FROM Sales WHERE alphacode >= AAA; Otra t ecnica es utilizar COUNT() con un ndice para hacer m as r apida la respuesta. Por ejemplo:

65

SELECT COUNT(invoice_nbr) FROM Sales; Es m as veloz que la versi on COUNT(*) si invoice nbr es una llave primaria u otra columna con ndice. Entregar informaci on extra a las consultas Un gestor de base de datos no siempre va a llegar a la misma conclusi on, a m as informaci on en la consulta mayor opci on a que el planicador encuentre un mejar plan. Por ejemplo, para usar JOIN en tres tablas diferentes sobre una misma columna se puede escribir:

SELECT * FROM Table1, Table2, Table3 WHERE Table2.common = Table3.common AND Table3.common = Table1.common; Pero se le entregar a mas informaci on al planicador para que decida que tabla es m as peque na y empezar por esta.

SELECT * FROM Table1, Table2, Table3 WHERE Table1.common = Table2.common AND Table2.common = Table3.common AND Table3.common = Table1.common;

El predicado IN Hay dos formas para uitlizar el IN, pasar una lista expl cita de valores o una subconsulta que genere esta lista de valores. El motor de base de datos no tiene estad sticas acerca de la relativa frecuencia de los valores en una lista de constantes por lo que asumir a que la lista estar a en el orden en que ser a utilizada por lo que es mejor ordenar una lista de los valores m as utilizados a los menos utilizados. Adem as, tampoco tiene sentido utilizar valores duplicados en una lista de constantes, ya que solose elegir a uno, el primero que se encuentre. Evitar expresiones matem aticas en columnas con ndices Si una columna aparece en una expresi on matem atica, el gestor no podr a utilizar sus ndices. Por ejemplo, dada una consulta que busca las tareas que demoran tres d as de completar en 1994: 66

SELECT task_nbr FROM Tasks WHERE (finish_date - start_date) = INTERVAL 3 DAY AND start_date >= CAST (2005-01-01 AS DATE); Pero si se tiene un ndice en la columna nish date (debido a lo frecuente de su uso) no se estar a utilizando, por lo que la siguiente consulta se ejecutar a m as r apido:

SELECT task_nbr FROM Tasks WHERE finish_date = (start_date + INTERVAL 3 DAY) AND start_date >= CAST (2005-01-01 AS DATE); Sin embargo, la primera consulta puede ser buena para columnas en tablas peque nas en las que solo se requiera b usqueda secuencial. Evitar el ordenamiento En lo posible evitar operaciones de ordenamiento como SELECT DISTINCT y ORDER BY. En el caso de DISTINCT, su hay columnas mcon valores u nicos como un primary key, PostgreSQL lo convertir a en un SELECT simple. [1] Se puede reemplazar un SELECT DISTINCT con un EXIST(), por ejemplo, si se quiere hallar los estudiantes que estudian ciencia:

SELECT DISTINCT S1.name FROM Students AS S1, ScienceDepts AS D1 WHERE S1.dept = D1.dept; Esta consulta puede ser reemplazada por:

SELECT S1.name FROM Students AS S1 WHERE EXISTS (SELECT * FROM ScienceDepts AS D1 WHERE S1.dept = D1.dept);

67

5.6.

Par ametros para el planeamiento de consultas

Algunos par ametros pueden ser establecidos en una transacci on para ayudar a mejorar el rendimiento.

5.6.1.

eective cache size

El valor por defecto es 128MB y es un par ametro utilizado para representar cuanta espacio de cache hay para la base de datos. Generalmente es m as de la mitad de la memoria RAM en un servidor dedicado. Este par ametro no reserva memoria solo sirve como un valor de referencia para el planicador sobre la capacidad disponible. Lo u nico para lo que se utiliza es para estimar cuando un Indice va a entrar en memoria, siendo la alternativa una b usqueda secuencial. Otras consultas donde este par ametro inuye son los CROSS JOINS que utilizan un Indice. as efectivo denirlo para las grandes transacciones y dejar un Para utilizar eective cache size es m valor conservador por defecto.

5.6.2.

work mem

ametro puede ser denido por cada transacci on, asignandole Al igual que eective cache size, este par valores grandes para las transacciones que lo requieran y un valor conservador por defecto.

5.6.3.

Optimizando las consultas para la data en cache

PostgreSQL asume que la data no est a en cache al hacer el planeamiento de una consulta por lo que todo acceso a un Indice o una tabla requerir a acceso a disco. Los par ametros del planicador seq page cost y random page cost reejan este pesimismo. Si la data que se va a leer se espera que este en cache, se pueden volver m as optimistas los par ametros del planicador, haciendolos m as cercanos al costo de acceder al nodo de un ndice (cpu index tuple cost ). Dado que ambos par ameros pueden ser establecidos en cada transacci on, se pueden tener valores conservadores como valor por defecto y solo a las consultas m as frecuentes, con alta probabilidad de que sus resultados ya esten en memoria, asignarles valores m as optimistas, incluso iguales a cpu index tuple cost.

SET seq_page_cost=0.005; SET random_page_cost=0.005;

5.7.

Comprobar la equivalencia de un query

En caso se haya escrito una consulta que se considera equivalente a otra pero m as r apida, para comprobar si dos consultas son equivalentes se utiliza EXCEPT para ver que registros devueltos por la

68

primera consulta no son devueltos por la segunda. Por ejemplo:

SELECT prod_id FROM products p WHERE NOT EXISTS (SELECT 1 FROM orderlines ol WHERE ol.prod_id=p.prod_id) EXCEPT SELECT prod_id FROM inventory WHERE sales=0;

5.8.

EXPLAIN ANALYZE gr aco

El administrador gr aco de PostgreSQL, PgAdmin, posee la capacidad de explicar de forma gr aca los resultados de EXPLAIN ANALYZE. Proporciona un sustituto f acil de leer e interpretar que puede ser utilizado en conjunto con la salida de texto de EXPLAIN ANALYZE. Para utilizar esta funcionalidad:

1. Abrir PgAdmin. 2. Hacer click en el cono de SQL. 3. Escribir una consulta. 4. presionar F7.

Gr aco 5.1: EXPLAIN ANALYZE gr aco en PgAdmin

69

Ejercicios 1. Ejecutar las consultas relativas a dellstore2 en el analizador visual de PgAdmin.

70

Cap tulo 6 Alta disponibilidad y replicaci on


En ocasiones, cuando se busca mejorar el rendimiento de una Base de Datos, lo m as pr actico es agregar m as copias de la data y dividir la carga de trabajo entre todas.

6.1.

Replicaci on

Se pueden enumerar diversas razones por las cu ales replicar la data, pero en esencia son dos las m as importantes: Disponibilidad y escalabilidad. Si el servidor principal se cae se espera que otro asuma de inmediato su rol. Debido al gran tama no de muchas bases de datos no se puede esperar copiar la data en el acto, en cambio se debe tener replicado el servidor. La escalabilidad signica que agregando servidores se pueda incrementar el n umero de accesos a la base de datos sin por eso perjudicar el rendimiento.

6.1.1.

Conceptos de replicaci on

Para entender la replicaci on se deben comprender los conceptos utilizados. Maestro: Es el servidor fuente de la data replicada y donde todas las actualizaciones suceden. Solo se puede tener un solo maestro al utilizar las funcionalidades de replicaci on de PostgreSQL. Esclavo: Un servidor esclavo es aquel donde se copia la data. PostgreSQL solo soporta esclavos de solo lectura. Write Ahead Log (WAL): Es el log que registra todas las transacciones. Es frecuentemente referido como el registro de transacciones en otras Bds. Para la replicaci on, PostgreSQL hace el registro disponible para los esclavos, una vez que los accceden solo necesitan ejecutar las transacciones en si mismos. S ncrono: Una transacci on en el maestro no se considera completa hasta que todos los esclavos no se han actualizado. As ncrono: Una transacci on en el maestro se va a realizar as los esclavos no se hayan actualizado. Esto es u til en el caso de servidores distantes donde la latencia de la red es una dicultad. La desventaja es que la data en el esclavo puede quedar desactualizada. 71

Streaming: El modelo de replicaci on por streaming fue introducido en la versi on 9.0. No requiere acceso directo a los archivos entre maestro y esclavo y se basa en el protocolo de de conexi on de PostgreSQL para transmitir los WALs. Replicaci on en cascada: Introducido en la versi on 9.2, los esclavos pueden recibir logs de otros esclavos, lo cu al permite a un esclavo actuar como un maestro pero nada m as que para consultas de solo lectura.

6.1.2.

Congurar una r eplica

Para el ejemplo de replicaci on se utilizar a la replicaci on por Streaming de manera tal que el maestro y el esclavo se conecten mediante el protocolo de conexi on de PostgreSQL. Congurar el maestro Los pasos b asicos para congurar el maestro son: 1. El par ametro listen addresses de postgresql.conf debe permitir conexiones del esclavo. 2. Crear una cuenta de usuario para la r eplica. CREATE ROLE pgrepuser REPLICATION LOGIN PASSWORD woohoo; 3. Alterar las siguientes conguraciones es postgresql.conf. wal level = hot standby archive mode = on max wal senders = 10 4. Usar el par ametro archive command para indicar donde el WAL va a ser salvado. Con streaming se puede escoger cualquier directorio pero debe asegurarse de que el usuario postgres pueda escribir en este. En *nix el par ametro tendr a un aspecto como el siguiente: archive command = cp %p ../archive/ %f Y en Windows: archive command = copy %p ..\\archive\\ %f 5. En pg hba.conf, se coloca una regla para permitir que los esclavos sean agentes de replicaci on. Como ejemplo, la siguiente regla va a permitir a una cuenta de usuario llamada pgrepuser en la red privada con una IP en un rango entre 192.168.0.1 y 192.168.0.254 que utiliza una contrase na en md5. host replication pgrepuser 192.168.0.0/24 md5

72

6. Desactivar el servicio Postgresql y copiar del directorio de datos (se puede ver la ruta del directorio de la instalaci on espec ca en el par ametro data directory de postgresql.conf ) todos los directorios al directorio de datos del esclavo EXCEPTO los directorios pg xlog y pg log. Congurar el esclavo Para minimizar problemas, el esclavo debe tener la misma conguraci on del maestro, especialmente si se va a utilizar como reemplazo en caso de una ca da. Adem as de la conguraci on, para ser un esclavo necesita reproducir las transacciones en el WAL (journal de la BD) del maestro. Para lo cu al se necesitan las siguientes instrucciones en el postgresql.conf de la Bd. 1. Crear una nueva instancia de PostgreSQL con la misma versi on que el maestro y adem as el mismo S.O. Esto no es un requerimiento estricto pero es recomendable. 2. Desactivar PostgreSQL. 3. Reescribir los archivos del directorio de datos con los archivos copiados del maestro. 4. Establecer el siguiente par ametro en postgresql.conf. hot standby = on 5. Se puede utilizar el puerto por defecto o no, no es necesario que utilice el mismo del maestro. 6. Crear un nuevo archivo en el folder de datos llamado recovery.conf que contenga las siguientes l neas. standby mode = on primary conninfo = host=192.168.0.1 port=5432 user=pgrepuser password=woohoo trigger le = failover.now El nombre del Host, el IP y el puerto deben ser los del maestro. 7. Agregar al archivo recovery.conf la siguiente l nea dependiendo del S.O,pero debe asegurarse de que el usuario postgres pueda escribir en este: En un *nix: restore command = cp %p ../archive/ %f En Windows: restore command = copy %p ..\\archive\\ %f Estos comando solo son necesarios si el esclavo no puede reproducir el WAL del maestro con suciente velocidad, por lo cu al necesita ponerlos en cache.

73

Iniciar el proceso de replicaci on 1. Iniciar el esclavo primero, si da un error sobre la falta de maestro, ignorarlo. 2. Iniciar el maestro. Cuando se desee liberar el esclavo, se crea un archivo en blanco llamado failover.now en el directorio de datos del esclavo. Luego de crear este archivo PostgreSQL va a renombrar el archivo recover.conf a recover.done y va a convertirse en un servidor independiente a partir de ese momento.

74

Cap tulo 7 Particionado de tablas


Al crecer una base de datos, es com un que alguna tabla se convierta en inmanejable por su tama no. Si la tabla es m as grande que la memoria del sistema el tiempo de consultas puede hacerse cada vez mayor. Una forma de lidiar con grandes tablas es particionarlas, dividi endolas en tablas m as peque nas y manejables. Para llevar a cabo esta tarea, no se necesita cambiar la aplicaci on debido a que Postgresql se hace cargo de gestionar las tablas.

7.1.

Particionado

Para saber cuando particionar una tabla, los criterios que se consideran como buenas pr acticas son hacerlo cuando la tabla sea m as grande que la memoria f sica o cuando alcance unos 100 millones de registros. Por ejemplo, considerando la tabla orders de la base de datos dellstore2 :

\d orders;

orderid

| integer

| not null valor por omision nextval(orders_orderid_seq::regclass)

orderdate customerid netamount tax

| date | integer

| not null |

| numeric(12,2) | not null | numeric(12,2) | not null

totalamount | numeric(12,2) | not null Si despu es de a nos de trabajo la tienda ha recibido tantas o rdenes que las consultas a la tabla se hacen muy lentas, hay dos potenciales maneras de partir la data en partes m as peque nas. La primera ser a partir la tabla de acuerdo a su id (orderid ). Otra forma es partirlo por fechas (orderdata ). La diferencia entre ambos es que al partirlo por orderid si se eliminan los antiguos pedidos de la base de datos, dejar a una gran cantidad de registros para ser limpiados lo que har a m as lenta la 75

base de datos. En cambio, si se utilizan fecha para partir la data, al querer eliminar data antigua, simplemente se borran las particiones que la contienen y el rendimiento de la base de datos no sufre. Otro criterio importante al partir una tabla es que para beneciarse de partir una tabla en pedazos, las consultas deben realizarse sobre un subconjunto u til de la data. Se deben tomar en cuentas los campos utilizados en la clausula WHERE como elementos para tomar la decisi on de que campo utilizar para dividir la tabla.

7.2.
7.2.1.

M etodos de Particionado
Conguraci on de Particionado

Un u til paso inicial antes de efectuar la partici on es obtener el rango de datos que contiene la tabla en relaci on al campo por el que se desea particionar y su tama no.

SELECT min(orderdate),max(orderdate) FROM orders;

2004-01-01 | 2004-12-31

SELECT relname,relpages FROM pg_class WHERE relname LIKE orders% ORDER BY relname;

orders

94 1 29

orders_orderid_seq | orders_pkey |

7.3.

Crear las particiones

Particionar en PostgreSQL se basa en las capacides de herencia de la tabla. Esto permite a una tabla tener hijos que hereden sus columnas. En este ejemplo se partir a la tabla orders en una partici on por mes.

CREATE TABLE orders_2004_01 ( CHECK ( orderdate >= DATE 2004-01-01 and orderdate < DATE 2004-02-01) ) INHERITS (orders);

...

76

...

CREATE TABLE orders_2004_12 ( CHECK ( orderdate >= DATE 2004-12-01 and orderdate < DATE 2005-01-01) ) INHERITS (orders); Pero solo se hereda la estructura de columnas de la tabla, para agregar ndices, restricciones y ajustar permisos se debe de hacer de forma manual:

ALTER TABLE ONLY orders_2004_01 ADD CONSTRAINT orders_2004_01_pkey PRIMARY KEY (orderid); ... ALTER TABLE ONLY orders_2004_12 ADD CONSTRAINT orders_2004_12_pkey PRIMARY KEY (orderid); SQLs que van a crear un ndice en orderid. Adem as un ndice manual en customerid es necesario:

CREATE INDEX ix_orders_2004_01_custid ON orders_2004_01 USING btree (customerid);

... ...

CREATE INDEX ix_orders_2004_12_custid ON orders_2004_12 USING btree (customerid); Cada orden contiene una restricci on a la llave for anea para asegurar que el cliente referenciado sea v alido. Debe ser aplicada a cada partici on:

ALTER TABLE ONLY orders_2004_01 ADD CONSTRAINT fk_2004_01_customerid FOREIGN KEY (customerid) REFERENCES customers(customerid) ON DELETE SET NULL;

... ...

77

ALTER TABLE ONLY orders_2004_12 ADD CONSTRAINT fk_2004_12_customerid FOREIGN KEY (customerid) REFERENCES customers(customerid) ON DELETE SET NULL;

7.3.1.

Redirigir los INSERT a las particiones

Luego de tener la estructura lista, el siguiente paso es hacer que los registros insertados en la tabla padre vayan a la partici on apropiada. La forma recomendada de hacerlo es con un trigger.

CREATE OR REPLACE FUNCTION orders_insert_trigger() RETURNS TRIGGER AS $$ BEGIN IF (NEW.orderdate >= DATE 2004-12-01 AND NEW.orderdate < DATE 2005-01-01 ) THEN INSERT INTO orders_2004_12 VALUES (NEW.*);

ELSIF

( NEW.orderdate >= DATE 2004-11-01 AND

NEW.orderdate < DATE 2004-12-01 ) THEN INSERT INTO orders_2004_11 VALUES (NEW.*);

...

ELSIF ( NEW.orderdate >= DATE 2004-01-01 AND NEW.orderdate < DATE 2004-02-01 ) THEN INSERT INTO orders_2004_01 VALUES (NEW.*); ELSE RAISE EXCEPTION Error in orders_insert_trigger(): date out of range; END IF;

RETURN NULL; END; $$ LANGUAGE plpgsql; Para hacerla m as corta solo se utilizar a la correspondiente a Enero,pero es una pr actica recomendada 78

empezar la funci on en el n del rango (Diciembre), debido a que en escenarios de negocios, lo m as probable es que se inserte data al nal del rango:

CREATE OR REPLACE FUNCTION orders_insert_trigger() RETURNS TRIGGER AS $$ BEGIN IF (NEW.orderdate >= DATE 2004-02-01 AND NEW.orderdate < DATE 2005-03-01 ) THEN INSERT INTO orders_2004_02 VALUES (NEW.*);

ELSIF

( NEW.orderdate >= DATE 2004-01-01 AND

NEW.orderdate < DATE 2004-02-01 ) THEN INSERT INTO orders_2004_01 VALUES (NEW.*); ELSE RAISE EXCEPTION Error in orders_insert_trigger(): date out of range; END IF; RETURN NULL; END; $$ LANGUAGE plpgsql; Una vez que la funci on ha sido creada, necesita ser llamada cada vez que un registro se inserte:

CREATE TRIGGER insert_orders_trigger BEFORE INSERT ON orders FOR EACH ROW EXECUTE PROCEDURE orders_insert_trigger(); La funci on puede necesitar actualizarse a medida que se agregan nuevas particiones, pero el trigger utilizar a la nueva funci on de manera autom atica una vez creada. Para probar si funciona insertamos un registro en el rango de fechas deseado:

INSERT INTO orders (orderdate, customerid, netamount, tax, totalamount) VALUES (2004-01-31, 6765, 359.03, 29.62, 388.65); Y comprobamos que se haya insertado en la tabla orders 2004 01.

79

7.3.2.

Utilizar reglas de partici on

Existe otra manera de implementar la redirecci on a la partici on llevada a cabo mediante el trigger. Mediante una funcionalidad llamada rules (reglas) de PostgreSQL se puede substituir un comando por otro que se desee. Para implementar la regla, se elimina el trigger:

DROP TRIGGER insert_orders_trigger ON orders; Y se crea la regla:

CREATE RULE orders_2004_01_insert AS ON INSERT TO orders WHERE ( orderdate >= DATE 2004-01-01 AND orderdate < DATE 2004-02-01 ) DO INSTEAD INSERT INTO orders_2004_01 VALUES (NEW.*); Y comprobamos si funciona insertando un registro. La ventajas de las reglas es que son m as ecientes insertando grandes cantidades de registros al mismo tiempo, pero los triggers son superiores al insertar registros de uno en uno. Y debido a que las reglas son proporcionales al n umero de particiones, el rendimiento puede disminuir a medida que aumentan las particiones. En pocas palabras es mejor utilizar triggers para particionar tablas.

7.3.3.

Trigger para los Updates

Cuando en la tabla maestra se actualizan registros, estos deben guardarse no en la tabla maestra sino en la partici on correspondiente. Con este n se instala el siguiente trigger:

CREATE OR REPLACE FUNCTION orders_2004_01_update_trigger() RETURNS TRIGGER AS $$ BEGIN IF ( NEW.orderdate != OLD.orderdate ) THEN DELETE FROM orders_2004_01 WHERE OLD.orderid=orderid; INSERT INTO orders values(NEW.*); END IF; RETURN NULL;

80

END; $$ LANGUAGE plpgsql;

CREATE TRIGGER update_orders_2004_01 BEFORE UPDATE ON orders_2004_01 FOR EACH ROW EXECUTE PROCEDURE orders_2004_01_update_trigger();

7.3.4.

Migraci on de la data

Luego de crear las particiones, los ndices y las funciones ahora se tiene toda la data en la tabla orders y particiones vacias. Esta es la forma habitual como se llevar a a cabo la partici on de la data para no interrumpir el funcionamiento de la aplicaci on. Otra opci on es hacer un backup de la tabla, crear la estructura de las particiones y recargar la data, lo que requeriria una ventana de mantenimiento. Otro m etodo es si se instala el trigger para los updates en la tabla padre, al actualizarse toda la tabla se migrar a la data. Este es el c odigo necesario:

CREATE OR REPLACE FUNCTION orders_update_trigger() RETURNS TRIGGER AS $$ BEGIN DELETE FROM orders WHERE OLD.orderid=orderid; INSERT INTO orders values(NEW.*); RETURN NULL; END; $$ LANGUAGE plpgsql;

CREATE TRIGGER update_orders BEFORE UPDATE ON orders FOR EACH ROW EXECUTE PROCEDURE orders_update_trigger(); Al llevar a cabo una migraci on, la aproximaci on m as prudente es incluir todo en un BEGIN/COMMIT, de tal manera que si algo sale mal, nada se lleva a cabo.

81

Para ejecutar la funci on se llama al trigger:

UPDATE orders SET orderid=orderid WHERE ORDERDATE < 2004-03-01; Luego se hace un count de las particiones:

SELECT count(*) FROM orders_2004_01; Se observa que las particiones tienen la data correspondiente pero que la tabla padre a un tiene toda la data. Para limpiar la tabla padrea se utilizar a CLUSTER para reconstruirla.

CLUSTER orders USING ix_order_custid; Luego se eliminan el trigger y la funci on que realizar on la migraci on para evitar futuras confuciones:

DROP TRIGGER update_orders ON orders; DROP FUNCTION orders_update_trigger(); Se ejecuta ANALYZE para actualizar las estad sticas de la base de datos y se verica que constraint exclusion este activa.

ANALYZE; SHOW constraint_exclusion; Constraint exclusion permite al planicador evitar incluir particiones en una consulta cuando estas no van a proveeder de registros relevantes. Se puede volver a ejecutar una consulta con toda la tabla y vericar las estad sticas:

EXPLAIN ANALYZE SELECT * FROM orders; QUERY PLAN ---------Result (cost=0.00..1292.00 rows=12001 width=36) (actual time=4.453..102.062 rows=12000 loops=1) -> Append (cost=0.00..1292.00 rows=12001 width=36) (actual time=4.445..62.258 rows=12000 loops=1) -> Seq Scan on orders (cost=0.00..400.00 rows=1 width=36) (actual time=4.153..4.153 rows=0 loops=1) -> Seq Scan on orders_2004_01 orders (cost=0.00..77.00 82

rows=1000 width=36) (actual time=0.287..1.971 rows=1000 loops=1) -> Seq Scan on orders_2004_02 orders (cost=0.00..77.00 rows=1000 width=36) (actual time=0.267..2.045 rows=1000 loops=1) Para probar el valor de las particiones, se puede probar con una consulta que solo consulte un d a puntual:

EXPLAIN ANALYZE SELECT * FROM orders WHERE orderdate=2004-01-16; QUERY PLAN ---------Result (cost=0.00..471.50 rows=36 width=36) (actual time=1.437..2.141 rows=35 loops=1) -> Append (cost=0.00..471.50 rows=36 width=36) (actual time=1.432..2.017 rows=35 loops=1) -> Seq Scan on orders (cost=0.00..400.00 rows=1 width=36) (actual time=1.189..1.189 rows=0 loops=1) Filter: (orderdate = 2004-01-16::date) -> Seq Scan on orders_2004_01 orders (cost=0.00..71.50 rows=35 width=36) (actual time=0.238..0.718 rows=35 loops=1) Filter: (orderdate = 2004-01-16::date) Total runtime: 2.276 ms En lugar de recorrer todas las particiones, solo recorre aquella correspondiente a la fecha solicitada.

7.3.5.

Crear nuevas particiones

Cuando sea necesario crear nuevas particiones se debe modicar el trigger y la funci on relacionada de tal manera que continue funcionando sin novedad el particionado.

7.3.6.

Ventajas de las particiones

Existen diversas ventajas en usar particiones para una tabla: Las b usquedas son m as veloces. Es m as sencillo el mantenimiento de data hist orica. Si se desea eliminar un rango de fechas del servidor de producci on, se hace un backup y se eliminan las particiones con la data antigua. Al eliminar data, esta no queda ocupando espacio, es eliminada junto con la partici on borrada

83

7.3.7.

Errores al particionar

Existen algunos errores comunes al particionar una tabla: No tener constraint exclusion en ON. No agregar todas los constrains e ndices necesarios a cada partici on. No asignar los permisos necesarios a las particiones. No utlizar el campo por el que se particiono al hacer consultas. No escribir robustos el trigger o la funci on.

84

Cap tulo 8 Pooling de conexiones


Cuando se trabaja con PostgreSQL, y cualquier gestor de bases de datos, una de sus limitaciones es el sobrecosto que se paga al ejecutar incluso la m as peque na consulta. El sobrecosto se acepta sin problemas si se est a llevando a cabo un complejo JOIN, pero si solo se efectua una lectura simple, el sobrecosto de abrir una conexi on a la base de datos y esperar a que se ejecute la consulta puede ser muy alto.

8.1.

El pool de conexiones

La raz on principal para utilizar un pool de conexiones es que se deben tener sucientes conexiones para utilizar todos los recursos disponibles pero no m as que eso. La cantidad de conexiones depende de los n ucleos en el sistema, cuanto de la base de datos est a en memoria y la velocidad de los discos. Una vez que el servidor ya est a activo continuamente, toda conexi on nueva solo degrada su eciencia. Existen algunas reglas pr acticas para decidir si se tienen muchas conexiones. En una instalaci on de *nix, el punto en que agregar nuevas conexiones se vuelve oneroso est a entre las 500 y 1000 activas. En general tener menos conexiones abiertas es mejor, pero no se recomienda utilizar un pool de conexiones hasta que el servidor este sobrecargado de trabajo. [5] En los sistemas Windows, el l mite es menor. Al ejecutar PostgreSQL como servicio, se le asignan 512KB para trabajar, por lo que si cada conexi on toma 3.5KB de espacio no se pueden tener m as de 125. Para m as informaci on al respecto se puede ver en: http://wiki.postgresql.org/wiki/Running %26 Installing PostgreSQL On Native Windows. Realizar pooling de conexiones va a ayudar si se tienen cientos o m as conexiones y los procesadores est an siendo utilizados en un elevado porcentaje.

8.2.

PgBouncer

Originado como parte de Skype, PgBouncer es el software para pooling con el mayor rendimiento disponible. Se ejecuta como un solo proceso, no abriendo un proceso por cada conexi on.

85

Al monitorear las conexiones, despliega la informaci on mediante una interfaz de base de datos a la que se le pueden aplicar consultas, sirviendo para proveer informaci on y de consola de control. Al conectarse mediante psql al puerto donde se ejecuta PgBouncer, se puede utilizar el comando SHOW para mostrar informaci on sobre el estado interno del pool de conexiones. PgBouncer se puede conectar con m ultiples bases de datos, ya sea en el mismo host o en diferentes, lo que permite una forma de particionar para escalar. Se mueve cada base de datos a su propio host y se les une mediante PgBouncer como intermediario y la aplicaci on no necesitar a ser cambiada.

8.2.1.

Instalaci on de PgBouncer

Para instalar PgBouncer en Ubuntu, ejecutar: $ sudo apt-get install pgbouncer

8.2.2.

Congurar PgBouncer

Para conectarse a una base de datos a trav es de PgBouncer se necesitan dos archivos de conguraci on ubicados en /etc/pgbouncer, uno donde se establecen los par ametros de conguraci on y conexi on y otro donde se denen los usuarios de la base de datos que podr an utilizar PgBouncer. El primero es pgbouncer.ini y el segundo userlist.txt : En pgbouncer.ini se escribir a la siguiente conguraci on:

[databases] template1 = host=127.0.0.1 port=5432 dbname=template1 Bd_prueba = host=127.0.0.1 port=5432 dbname=Bd_prueba

[pgbouncer] listen_port = 6543 listen_addr = 127.0.0.1 auth_type = md5 auth_file = userlist.txt logfile = pgbouncer.log pidfile = pgbouncer.pid admin_users = user En pgbouncer.ini user es el usuario que va administrar pgbouncer. Se agregan adem as los usuarios de la base de datos. Para agregar m as bases de datos solo se deben de agregar en la secci on [databases]. Y en userlist.txt :

86

"user" "password" Para iniciar PgBouncer ejecutar el comando: pgbouncer -d pgbouncer.ini Para conectarse a una base de datos a trav ez de PgBouncer escribir: psql -p 6543 -h localhost -U user-base-datos template1 Para conectarse a PgBouncer escribir: psql -p 6543 -h localhost -U user pgbouncer Al conectarse a PgBouncer, mediante SHOW HELP se pueden mostrar los comandos existentes:

SHOW HELP;

NOTICE: DETALLE:

Console usage

SHOW HELP|CONFIG|DATABASES|POOLS|CLIENTS|SERVERS|VERSION SHOW STATS|FDS|SOCKETS|ACTIVE_SOCKETS|LISTS|MEM SHOW DNS_HOSTS|DNS_ZONES SET key = arg RELOAD PAUSE [<db>] RESUME [<db>] KILL <db> SUSPEND SHUTDOWN SHOW Si se hacen cambios en pgbouncer.ini y se desea recargar el archivo de conguraci on:

RELOAD;

87

8.3.

PgPool II

Es el m as antiguo de los paquetes utilizados para pooling de conexiones con PostgreSQL que a un sigue en desarrollo. Su funci on principal no es solo el pooling de conexiones, adem as provee balanceo de carga y capacidades de replicaci on. Adem as soporta algunas conguraciones para consultas en paralelo, donde las consultas son partidas en pedazos y repartidas entre los nodos donde cada una tiene una copia de la informaci on solicitada. El pool en pgpool es sobre todo para gestionar m ultiples servidores, y pgpool sirve como proxy entre el cliente y cierto n umero de bases de datos. PgPool tiene algunas limitaciones en el pooling de conexiones. Cada conexi on es establecida en su propio proceso como en el servidor. El sobrecosto de memoria de esa aproximaci on, con cada proceso utilizando una porci on de memoria, puede ser signicativa. Adem as, en pgpool una vez se sobrepasa la cantidad de conexiones que maneja el software, las adicionales son encoladas en el sistema operativo, con cada conexi on esperando para que su conexi on de red sea aceptada.

8.3.1.

Instalar PgPool II

Para instalar PgPool II en Ubuntu ejecutar: sudo apt-get install pgpool2

8.3.2.

Conguraci on de PgPool II

Para congurar el origen de conexiones a PgPool, se abre el archivo pgpool.conf y se da el valor * al par ametro listen adresses. listen adresses = * Para congurar los usuarios que pueden acceder a la interfaz de administraci on se congura el archivo pcp.conf agregando el usuario y su password en md5. Para generar un password en md5 utilizamos el comando pg md5 y el password que deseamos cifrar: pg md5 123456 El resultado lo incluimos en pcp.conf : admin:e10adc3949ba59abbe56e057f20f883e

8.3.3.

Preparar los nodos de bases de datos

Se deben establecer los servidores PostgreSQL para PgPool. Estos servidores pueden estar en el mismo host donde se encuentra PgPool o en otro host. En el ejemplo el servidor estar a presente en el mismo host que PgPool. Para congurar se accede al archivo pgpool.conf y se escriben los siguientes par ametros:

88

backend hostname0 = localhost backend port0 = 5432 backend weight0 = 1 a ejecutando un solo servidor sin balanceo de carga. El par ametro backend weight0 indica que se est Si se desean m as servidores, se agrega m as par ametros cambiando el n umero para reejar el n umero del servidor.

8.3.4.

Activar PgPool II

Para activar pgpool-II, se utiliza el comando: pgpool -n -d > /tmp/pgpool.log 2>&1 & Esta instrucci on genera un log en /tmp/pgpool.log y se ejecuta en segundo plano. Para terminar el proceso se ejecuta: pgpool stop Si hay clientes conectados y se desea desactivar el servicio a la fuerza: pgpool -m fast stop

8.3.5.

Conectarse a PgPool II

El puerto por defecto gura en el archivo pgpool.conf, en el caso del presente ejemplo es 5433. Antes de ejecutarlo se debe cerrar cualquier programa que este editando un archivo de conguraci on de PgPool. Para saber si PgPool est a activo y aceptando conexiones ejecutar: ps -ef | grep pgpool root root root root root root root root root root 6586 6587 6588 6589 6590 6591 6592 6593 6594 6595 3013 6586 6587 6587 6587 6587 6587 6587 6587 6587 0 0 0 0 0 0 0 0 0 0 20:35 20:35 20:35 20:35 20:35 20:35 20:35 20:35 20:35 20:35 pts/1 pts/1 pts/1 pts/1 pts/1 pts/1 pts/1 pts/1 pts/1 pts/1 00:00:00 00:00:00 00:00:00 00:00:00 00:00:00 00:00:00 00:00:00 00:00:00 00:00:00 00:00:00 sudo pgpool -n -d pgpool -n -d pgpool: wait for connection pgpool: wait for connection pgpool: wait for connection pgpool: wait for connection pgpool: wait for connection pgpool: wait for connection pgpool: wait for connection pgpool: wait for connection

request request request request request request request request

Si todo est a conforme se ejecuta psql para conectarse a PgPool:

89

psql -p 5433 -h localhost -U pedro -d Bd prueba Una vez en la base de datos, adem as de los comandos SQL habituales, se pueden ver datos propios de PgPool como: pool pool pool pool pool status, to get the conguration nodes, to get the nodes information processes, to get information on pgPool-II processes pools, to get information on pgPool-II pools version, to get the pgPool-II release version

90

Cap tulo 9 Lenguajes Procedurales


Como en otras bases de datos, se pueden juntar expresiones SQL y volverlas una unidad. tiene diferentes nombres seg un el motor utilizado: procedimientos almacenados, m odulos, macros, etc. En PostgreSQL se llaman funciones y adem as de permitir juntar varias expresiones SQL, permiten tambi en utilizar l ogica para dirigir el ujo del programa. En PostgreSQL existen diversos lenguajes que se pueden utilizar para escribir funciones y que con frecuencia vienen ya empaquetados: SQL, C, PL/pgSQL, PL/Perl, PL/Python. Se pueden instalar adem as otrs lenguajes como R, Java, sh e incluso algunos experimentales como Scheme. Para ver una lista de los lenguajes disponibles acceder a: http://www.postgresql.org/docs/current/interactive/external-pl.html

9.1.

Estructura de una funci on

Sin importar que lenguaje se escoge para escribir una funci on, todas comparten una misma estructura:

CREATE OR REPLACE FUNCTION func_name( arg1 arg1_datatype) RETURNS some_type | setof sometype | TABLE (..) AS $$ BODY of function $$ LANGUAGE language_of_function Para listar la lista de lenguajes en la base de datos se ejecuta:

SELECT lanname FROM pg_language;

91

La denici on de una funci on puede incluir atributos adicionales para optimizar la ejecuci on y mejorar la seguridad:

LANGUAGE: Debe ser uno instalado en la base de datos. VOLATILITY: Por defecto es VOLATILE si no es especicado. Puede ser establecido como STABLE, VOLATILE o IMMUTABLE. Estas conguraciones le dan una idea al planicador sobre si los resultados de la funci on pueden ser colocados en la cache. STABLE signica que la funci on va a retornar el mismo valor para la misma entrada y la misma consulta. VOLATILE signica que la funci on puede retornar un valor diferente con cada llamada del sistema. INMUTABLE signica que dada una entrada, la salida siempre va a ser la misma. STRICT: Una funci on es asumida como no estricta a menos que tenga el atributo STRICT. Una funci on STRICT siempre retorna NULL si alguna entrada es NULL. COST: Es una medida relativa de la intensidad de computo. Las funciones SQL y PL/PgSQL tienen un valor por defecto de 100 y las de C de 1. Amayor el valor, se asume que la funci on es m as costosa. ROWS: Es un estimado de cuantos registros va a devolver la funci on. El formato es ROWS 100. SECURITY DEFINER: Cl ausula opcional que implica que la funci on se ejecuta en el contexto del due no dela funci on. Si no se coloca, la funci on se ejecuta en el contexto del usuario actual.

9.2.

Funciones SQL

Escribir funciones en SQL es sencillo. Se agrega la estructura y se tiene la funci on. Debido a que no es un lenguaje propiamente dicho, en SQL no hay estructuras de control. No puede haber m as de una sentencia SQL (se pueden utilizar sub consultas). Ejemplo:

CREATE OR REPLACE FUNCTION ins_logs(param_user_name varchar, param_description text) RETURNS integer AS $$ INSERT INTO logs(user_name, description) VALUES($1, $2) RETURNING log_id; $$ LANGUAGE sql VOLATILE; Para llamar a la funci on se ejecuta:

SELECT ins_logs(lhsu, this is a test) As new_id; Para retornar conjuntos de registros existes tres alternativas: RETURNS TABLE, usar par ametros OUT, o retornar un tipo de datos compuesto. [3]

92

Ejemplo de RETURNS TABLE:

CREATE FUNCTION sel_logs_rt(param_user_name varchar)

RETURNS TABLE (log_id int, user_name varchar(50), description text, log_ts timestamptz) AS $$ SELECT log_id, user_name, description, log_ts FROM logs WHERE user_name = $1; $$ LANGUAGE sql STABLE; Utilizando par ametros OUT:

CREATE FUNCTION sel_logs_out(param_user_name varchar, OUT log_id int , OUT user_name varchar, OUT description text, OUT log_ts timestamptz) RETURNS SETOF record AS $$ SELECT * FROM logs WHERE user_name = $1; $$ LANGUAGE sql STABLE; Usando un tipo de dato compuesto:

CREATE FUNCTION sel_logs_so(param_user_name varchar) RETURNS SETOF logs AS $$ SELECT * FROM logs WHERE user_name = $1; $$ LANGUAGE sql STABLE; Todas las funciones pueden ser llamadas usando:

SELECT * FROM sel_logs_rt(lhsu);

9.3.

Funciones PL/pgSQL

Cuando las necesidades escapan de los l mites del SQL puro, la opci on m as com un es PL/pgSQL. Se diferencia de SQL en que se pueden declarar variables utilizando DECLARE, existen instrucciones 93

de control de ujo y el cuerpo de la funci on debe de estar entre BEGIN y END. Ejemplo:

CREATE FUNCTION sel_logs_rt(param_user_name varchar) RETURNS TABLE (log_id int, user_name varchar(50), description text, log_ts timestamptz) AS $$ BEGIN RETURN QUERY SELECT log_id, user_name, description, log_ts FROM logs WHERE user_name = param_user_name; END; $$ LANGUAGE plpgsql STABLE;

9.4.

Funciones en PL/Python

Python es un lenguaje popular con gran cantidad de librer as. En PostgreSQL se pueden escribir funciones utilizando Python. Est an soportadas tanto Python 2 como Python 3. Para utilizar Python, se debe instalar el paquete de software que contiene la extensi on. en Ubuntu: sudo apt-get install postgresql-plpython-9.2 Luego se ingresa en la base de datos y se instala la extensi on:

CREATE EXTENSION plpython2u;

9.4.1.

Funci on python b asica

PostgreSQL convierte autom aticamente los tipos de PostgreSQL a tipos de dato Python y viceversa. Desde Pl/Pyton se pueden retornar arreglos e incluso tipos de datos compuestos. Se puede utilizar python para escribir Triggers y crear funciones de agregaci on. Pl/Python es un lenguaje untrusted debido a que puede interactuar con el sistema operativo y por lo tanto una funci on solo puede ser creada por un superusuario. Un usuario puede escribir funciones en PL/Python si es que al crearse se le dio el atributo SECURITY DEFINER. Los lenguajes untrusted se reconocen debido a que llevan una u al nal de su nombre.

94

Python permite llevar a cabo tareas que no son factible en SQL o PL/pgSQL. En el siguiente ejemplo se muestra como hacer una funci on que haga una b usqueda de texto en la web de documentaci on de PostgreSQL.

CREATE OR REPLACE FUNCTION postgresql_help_search(param_search text) RETURNS text AS $$ import urllib, re response = urllib.urlopen \ (http://www.postgresql.org/search/?u=%2Fdocs%2Fcurrent%2F&q=+param_search) raw_html = response.read() result = raw_html[raw_html.find("<!-- docbot goes here -->"):raw_html.find("<!-- \ pgContentWrap -->") - 1] result = re.sub(<[^<]+?>, , result).strip() return result $$ LANGUAGE plpython2u SECURITY DEFINER STABLE; Lo que hace la funci on es:

1. Importar las librer as a utilizar. 2. Concatenar el t ermino de b usqueda con la direcci on web. 3. Leer la respuesta y guardarla en una variable llamada raw html. 4. Guardar la parte de raw html que empieza con <! docbot goes here > y termina antes de <! pgContentWrap >. 5. Elimina los tags HTML y los espacios en blanco al inicio y nal y guarda en result. 6. Retorna el resultado nal result. Llamar a una funci on Python no es diferente que llamar a funciones en otros lenguajes:

SELECT search_term, left(postgresql_help_search(search_term), 125) As result FROM (VALUES (regexp_match), (pg_trgm), (tsvector)) As X(search_term); Otro ejemplo permitir a interactuar con el sistema operativo:

95

CREATE OR REPLACE FUNCTION list_incoming_files() RETURNS SETOF text AS $$ import os return os.listdir(/tmp) $$ LANGUAGE plpython2u VOLATILE SECURITY DEFINER; Para ejecutarlo:

SELECT * FROM list_incoming_files(); Ejemplo de acceso a data desde plpython mediante la librer a plpy.

CREATE FUNCTION try_adding_joe() RETURNS text AS $$ try: plpy.execute("INSERT INTO users(username) VALUES (joe)") except plpy.SPIError: return "something went wrong" else: return "Joe added" $$ LANGUAGE plpythonu;

CREATE FUNCTION count_odd_fetch(batch_size integer) RETURNS integer AS $$ odd = 0 cursor = plpy.cursor("SELECT num FROM largetable") while True: rows = cursor.fetch(batch_size) if not rows: break for row in rows: if row[num] % 2: odd += 1 return odd

96

$$ LANGUAGE plpythonu;

9.4.2.

Aspectos b asicos de Python

Python es un lenguaje de programaci on interpretado, din amico y multiparadigma (POO, estructurado). Se caracteriza por tener una baja curva de aprendizaje, ser multiuso y permitir una programaci on ordenada y elegante. Su visi on est a expresa en el Zen de Python: Bello es mejor que feo. Expl cito es mejor que impl cito. Simple es mejor que complejo. Python se ha utilizado para todo tipo de desarrollos incluyendo Web, aplicaciones de escritorio, sistemas de informaci on, utilitarios, etc.

9.4.3.

Ejemplo de Python

import smtplib from email.MIMEText import MIMEText

fromaddr = pmunoz@gmail.com toaddrs = pedro@simuder.com

msg = Hola, este es un mensaje de prueba

message = MIMEText(msg) message[From] = Example < + fromaddr message[To] = toaddrs message[MIME-Version] = 1.0 message[Content-type] = text/HTML message[Subject] = Asunto + >

# Credentials (if needed) usuario = usuario password = password 97

# The actual mail send server = smtplib.SMTP(smtp.gmail.com:587) server.starttls() server.login(usuario,password) server.sendmail(fromaddr, toaddrs, message.as_string()) server.quit() Para empezar a experimentar con Python se puede utilizar el int erprete interactivo desde la consola: python

9.4.4.

Tipos b asicos

Los tipos b asicos son en esencia tres: n umeros, cadenas y valores booleanos. N umeros: 5 (entero), 4.7 (otante), 4 + 6j (complejo). Cadenas: Gobierno regional. Booleanos: True y False Los comentarios se escriben utilizando el s mbolo #:

\# Este es un comentario a = "Esta es una linea de programa" Las variables se asignan de forma din amica y dependen del tipo de dato que se les asigna, por ejemplo, una variable puede ser entera, luego asignarsele un valor de coma otante y por u ltimo una cadena y es v alido:

>>> a = 5 >>> a 5 >>> a = 6.4 >>> a 6.4 >>> a = "Chiclayo" >>> a

98

Chiclayo >>>

Cadenas Existen tres tipo de cadenas: Las cadenas normales, las cadenas unicode y las cadenas crudas (raw en ingl es). >>> a = n >>> print a n >>> b = n >>> print b n >>> a u\xf1 >>> b \xc3\xb1 >>> c = r\n >>> c \\n >>> print c \n >>>

9.4.5.

Operadores
Operador + * ** / // % Descripci on Suma Resta Negaci on Multiplicaci on Exponente Divisi on Divisi on entera M odulo Ejemplo r = 3 + 2 # r es 5 r = 4 - 7 # r es -3 r = -7 # r es -7 r = 2 * 6 # r es 12 r = 2 ** 6 # r es 64 r = 3.5 / 2 # r es 1.75 r = 3.5 // 2 # r es 1.0 r=7

Si en una operaci on utilizamos un n umero otante y un entero el resultado ser a otante.

99

9.4.6.

Colecciones

Los tipos de colecciones de datos m as utilizados en Python son: listas, tuplas y diccionarios.

Listas Las listas son el caballo de batalla de Python. Son colecciones de datoa que pueden tener cualquier tipo de dato: n umeros, cadenas, otras listas, objetos, etc. Para crear una lista se agrupan los objetos en corchetes separados por comas:

>>> l = [22, True, "una lista", [1, 2]] >>> l[2] una lista >>> l[3][0] 1 >>> l[1] = 15 >>> l [22, 15, una lista, [1, 2]] >>> >>> l[0:2] [22, 15] >>> l[:2] [22, 15] >>> l.append("mee") >>> l [22, 15, una lista, [1, 2], mee]

Tuplas Las tuplas se parecen a las listas, excepto por dos puntos: Se denen de forma diferente y son inmutables.

>>> tupla = (1,5,"Hola", True, "Hotel") >>> tupla[0] 1 >>> tupla[0:2]

100

(1, 5) >>> t = (1) >>> type(t) <type int> >>> t = (1,) >>> type(t) <type tuple> A cambio de no ser modicables, las tuplas son m as ligeras en memoria. Diccionarios Son colecciones que relacionan una llave y un valor. El primer valor es la clave y el segundo el valor asociado a la clave. Como clave se puede utilizar cualquier valor inmutable: n umeros, cadenas, booleanos, tuplas. A un diccionario se accede solo por la llave, ya que no tienen orden interno.

>>> d = {"Don Corleone": "Marlon Brando", "Michel Corleone": "Al Pacino"} >>> d {Michel Corleone: Al Pacino, Don Corleone: Marlon Brando} >>> d["Don Corleone"] Marlon Brando

9.4.7.

Control de ujo

El control de ujo son los condicionales y bucles:

x = 10 y = 50

if x > 10 and y > 60: print "x mayor que 10 e y mayor que 60" elif x > 5 and y < 100: print "x mayor que 5 e y menor que 100" else: print "ninguna de las anteriores"

101

En Python no existe el switch.

i = 0

while i < 20: print str(i) + " es menos de 20" i = i + 1 En Python, el bucle for ... in se utiliza como una forma gen erica de iterar sobre una secuencia.

x = 5 for j in range(x): print "a " + str(j) + " le faltan " + str(x - j) + " para alcanzar a " + str(x)

l = [4, "Segundo", "Chiclayo", False, 6.8]

for item in l: print item

9.4.8.

Funciones

Una funci on es un fragmento de c odigo con un nombre asociado que realiza una serie de tareas y devuelve un valor.

def primera_funcion(param1, param2):

suma = param1 + param2 return suma

print primera_funcion(5,4) print "\n" print primera_funcion("Ho","la")

def varios(param1, param2, *otros): """Funcion con numero variable de parametros:W

102

""" print param1 print param2 for val in otros: print val

varios(1,2) varios(1,2,3,4) varios(1,2,3,4,5)

9.4.9.

Funciones Trigger

PostgreSQL ofrece Triggers a nivel de registro y de tablas y vistas. PostgreSQL ofrece funciones especializadas en gestionar los triggers que actuan como cualquier otra funci on y tienen la misma estructura b asica. Donde dieren es en el par ametro de entrada y en la salida. Una funci on trigger nunca recibe un input aunque internamente tiene acceso a la data del trigger y puede modicarla. Su salida siempre es un tipo llamado trigger. Cada trigger debe tener asociada unafunci on trigger y para tener m ultiples triggers se deben crear m ultiples funciones sobre el mismo evento las cuales se ejecutaran en orden alfab etico. Se puede usar cualquier lenguaje menos SQL para escribir triggers. El m as utilizado es PL/pgSQL. Se siguen dos pasos: en primer lugar escribir la funci on y luego el trigger correspondiente. Por ejemplo:

CREATE OR REPLACE FUNCTION orders_2004_01_update_trigger() RETURNS TRIGGER AS $$ BEGIN IF ( NEW.orderdate != OLD.orderdate ) THEN DELETE FROM orders_2004_01 WHERE OLD.orderid=orderid; INSERT INTO orders values(NEW.*); END IF; RETURN NULL; END; $$

103

LANGUAGE plpgsql;

CREATE TRIGGER update_orders_2004_01 BEFORE UPDATE ON orders_2004_01 FOR EACH ROW EXECUTE PROCEDURE orders_2004_01_update_trigger();

Lo primero que se hace es denir la funci on trigger que elimina un valor antiguo e inserta el valor nuevo del registro. El trigger se ejecutar a antes de que se actualize un registro de la tabla orders 2004 01.

104

Cap tulo 10 Extensiones y contrib


Las extensiones y los m odulos contribs son Add-ons que se pueden instalar en una base de datos para extender su funcionalidad m as all a de lo que ofrece PostgreSQL. Antes de PostgreSQL 9.1 los add-ons se llamaban contribs, a partir de esa versi on, los add-ons son instalados con facilidad mediante el nuevo modelo de extensiones, t ermino que ha reemplazado a contrib. Las extensiones son instaladas por separado en cada base de datos. Se puede tener una base de datos con una extensi on y las dem as no tenerla. Si se desea que todas las bases de datos tengan un esquema, este se debe instalar en la base de datos template1 para que al crearse una nueva, tenga a su vez la extensi on deseada. Para ver las extensiones instaladas se ejecuta: SELECT * FROM pg available extensions; Para tener los detalles de una extensi on en particular se utiliza el siguiente comando: \dx+ plpgsql

10.1.

Instalar Extensiones

Para instalar una extensi on se deben de colocar sus scripts en share/extension y sus binarios en lib y bin. En el caso de las extensiones m as comunes, estas ya se encuentran precompiladas y solo falta instalarlas. La forma moderna y sencilla de instalar una extensi on es: CREATE EXTENSION fuzzystrmatch; Si se desea instalar la extensi on en un esquema particular, primero se crea el esquema y luego se instala la extensi on: CREATE EXTENSION fuzzystrmatch SCHEMA my extensions;

105

10.2.

Extensiones Comunes

Diversas extensiones vienen empaquetadas con PostgreSQL pero no son instaladas por defecto. Algunas de las m as populares son:

Postgis: Una extensi on que coloca a PostgreSQL entre las principales bases de datos geogr acas. Est a compuesto de m as de 800 funciones, tipos e ndices espaciales. fuzzystrmatch: Es una extensi on ligera para trabajar de forma difusa con cadenas. hstore: Es una extensi on que agrega almacenamiento por llave y valor (tipo diccionario) para para servir de intermedio entre relacional y NoSQL. guardar data pseudo normalizada. Util pg trgm: Una extensi on utilizada para manejar de forma difusa cadenas de texto. dblink: M odulo que permite hacer consultas a otras bases de datos. Es el u nico mecanismo para trabajar entre bases de datos con PostgreSQL. pgcrypto: Provee herramientas de cifrado incluyendo PGP.

106

Fuentes de Informaci on
[1] CELKO, JOE. SQL FOR SMARTIES: ADVANCED SQL PROGRAMMING THIRD EDITION. Morgan Kaufmann, 2005. [2] Group, The PostgreSQL Global Development. PostgreSQL 9.2.3 Documentation. PostgreSQL 9.2.3 Documentation, 2013. [3] Obe, Regina y Hsu, Leo. PostgreSQL: Up and Running. OReilly, 2012. [4] Qui nones, Ernesto. Postgresql como funciona una base de datos por dentro. [5] Smith, Gregory. PostgreSQL 9.0 High Performance. Packt Publishing, Birmingham UK., 2010.

107

Anda mungkin juga menyukai