Planeta PostgreSQL-es

18 mayo 2012

Samuel Zarza Fernandez

Transacciones autónomas en PostgreSQL


The cheapest, fastest, and most reliable components are those that aren’t there.
Gordon Bell.

En algunos casos, necesitamos que ciertas operaciones de una transacción de base de datos sean realizadas aunque la transacción se deshaga con un rollback. Por ejemplo, imaginemos que tenemos una función o procedimiento almacenado en la que hemos agrupado 10 operaciones. Cuando dicha función se llame, se ejecutará en un contexto transaccional, es decir, se realizará una transacción con dichas 10 operaciones de forma atómica (o todas, o ninguna). Supongamos que queremos garantizar que un subconjunto de esas operaciones (por ejemplo un par de ellas que hacen auditoría de la propia llamada) se realicen siempre, con independencia de las demás: en este caso necesitamos una transacción autónoma.

Las transacciones autónomas (Autonomous Transactions) permiten suspender el contexto de la transacción en curso (llamante), realizar una transacción independiente y reanudar el contexto de la transacción llamante sin afectar su estado. Los casos de uso típicos de uso son funcionalidades cuyos cambios queremos que persistan con independencia de la transacción que las llama: trazado (logging), operaciones de auditoría, contadores, funciones de propósito general...etc.

Un caso que se me ha dado recientemente es el de realizar una transacción batch muy muy larga (de importación de gran cantidad de  datos), donde la unidad de importación supone operaciones de modificación (inserción o actualización) en varias tablas. Imaginemos que importamos usuarios con todos sus datos: dirección, provincia, datos bancarios, teléfonos, etc... Cada usuario puede suponer 8 o 10 operaciones en diversas tablas. Si tenemos que importar 30.000 usuarios, podemos encontrarnos con una transacción compuesta por 300.000 operaciones de inserción/actualización. Este tipo de transacciones tan grandes exige muchos recursos de un servidor de base de datos: crea ocupación de memoria y genera muchos puntos de bloqueos que podrían socavar el desempeño de un sistema en producción. Una forma de solucionar un problema así es realizar una confirmación de datos por cada unidad de importación. Es decir, que el bucle general de importación (que ya se ejecuta en un contexto transaccional) llame a una función que realiza y confirma la tarea de importación de una unidad (un usuario en el ejemplo) en una transacción autónoma, con lo cual cada usuario se procesaría de forma atómica, sin que la transacción general acumule trabajo.

Con Oracle, las transacciones autónomas se declaran sin mayor dificultad usando la directiva:

PRAGMA AUTONOMOUS_TRANSACTION;

Sin embargo, en PostgreSQL las transacciones autonomas no están soportadas. No hay forma de hacerlo de forma declarativa. Sólo hay una forma de hacerlo (con dos enfoques, como veremos enseguida): realizando la parte que queremos que sea autónoma en otro contexto transaccional, es decir, en otra conexión a la base de datos:
  1. Usando un lenguaje de programación externo (untrusted).  Es decir, reducir la función PL/PgSQL a la parte que queremos garantizar su ejecución (la parte que queremos que sea autónoma) y realizar el resto en un lenguaje de programación externo a la base de datos. La función se llamará en una nueva conexión
  2. Usando dblink. Esta opción, es parecida a la anterior, pero usando siempre PL/PgSQL. Es decir, realizamos la transacción autónoma en una nueva conexión usando dblink.


dblink

dblink es un módulo del contrib de PostgreSQL que permite realizar conexiones y realizar consultas a bases de datos locales o remotas dentro de una sesión. Con un ejemplo se verá más claro:

SELECT nombre, apellidos
FROM usuario INNER JOIN
dblink('dbname=otrabasededatos port=5432 host=localhost_u_otro' ||
'user=usuario password=password',
'SELECT direccion, poblacion, provincia from usuario')
AS u(direccion varchar, poblacion varchar, provincia varchar)
ON usuario.id = u.id;

En el anterior ejemplo, realizamos un JOIN entre dos tablas de dos bases de datos distintas (en el mismo host u otro, eso da igual). Es decir, en la sesión en curso, y a través de las funciones de dblink, se crea una conexión sobre la que enviamos nuestra query. Si esto lo hacemos contra el mismo servidor y misma base de datos... voilá: ya tenemos una conexión nueva y, por tanto, un contexto transaccional diferente en el que podemos ejecutar nuestra transacción de forma independiente (es otra conexión).

Veamos un ejemplo de cómo usarlo. Supongamos el ejemplo del inicio, donde tenemos un cursor que recorremos en el que, para cada registro, debemos realizar un par de operaciones transaccionales de forma independiente (autónoma). Aprovecharemos el ejemplo también para ilustrar cómo se puede realizar una inserción y obtener la clave del elemento recién insertado para la siguiente sentencia.

for usuario in (select * from iusuarios) loop
raise notice 'Procesando usuario->, %',usuario.id || '-' || usuario.nombre;

PERFORM dblink_connect_u('dbname=dbname connect_timeout=5');
PERFORM dblink_exec('begin;');

l_dbl_sql :=
'insert into u2 (name,edad) values (' ||
quote_nullable(l_name) || ', ' ||
coalesce(l_edad::varchar,'null') || ', ' ||
'0) returning id;';
raise notice '[ALTA] SQL INSERT u2: %', l_dbl_sql;

select id into l_user_id from dblink(l_dbl_sql) as d(id int4);

l_dbl_sql :=
'update otra_tabla set date = now() where id_user = ' || l_user_id || ';';
raise notice '[ALTA] SQL UPDATE otra_tabla: %', l_dbl_sql;
PERFORM dblink_exec(l_dbl_sql);

PERFORM dblink_exec('commit;');
PERFORM dblink_disconnect();
end loop;

Examinaremos el ejemplo, porque hay cosas interesantes que quiero destacar:
  1. Linea 4: es importante especificar el timeout, para evitar efectos indeseables. Dado que se trata de la misma base de datos en el mismo servidor, no hay que especificar nada más.
  2. Linea 5: inicio de la transacción, ya que hay más de una sentencia
  3. Líneas 9 y 10: uso de las funciones quote_nullable() y coalesce() para garantizar el correcto escape de valores y la generación de 'null' cuando existan valores nulos.
  4. Línea 14: ejemplo de ejecución de sentencia INSERT con dblink para obtención del registro recién insertado.
  5. Línea 19: ejemplo de ejecución de sentencia UPDATE (o cualquier otra sentencia que no devuelva resultados)
  6. Línea 21: confirmación de la transacción
  7. Línea 22: desconexión
  8. Líneas 11 y 17: es muy importante asegurarse de que terminamos las sentencias que enviamos a dblink con el separador de terminación punto y coma (;). Un olvido puede hacer que nuestra función se detenga esperando la terminación.
Finalmente, recomiendo usar las funciones quote_nullable() para las fechas y cadenas y coalesce() para los valores numéricos para garantizar una correcta sintaxis y escapado de las sentencias. Si estás usando PostgreSQL 9.1 o superior puedes evitar ese engorro y usar la enormemente más cómoda función format().


Referencias y más información:

por Samuel Zarza Fernández (noreply@blogger.com) el 18 mayo 2012 07:08

16 mayo 2012

Rafael Martinez

Disponible PostgreSQL Magazine #01

comunidad

Hace unos dias se lanzo el primer número de la revista "PostgreSQL Magazine". Esta revista es la primera revista sin ánimo de lucro creada por y para la comunidad PostgreSQL.

Esperan que la gente colabore con artículos, correciones y traducciones. Si estas interesado en el tema pasate por http://pgmag.org.

El primer número está disponible en estos enlaces:

Leer online: http://pgmag.org/01/read
Descargar PDF: http://pgmag.org/01/download
Comprar la versión impresa: http://pgmag.org/01/buy

Que la disfruteis.
--
Rafael Martinez Guerrero
PostgreSQL-es

por rafaelma el 16 mayo 2012 01:14

16 marzo 2012

Jaime Casanova

Calentando motores con pgFincore

Hoy pase toda la mañana ayudando a un cliente con un problema que ya le estaba causando dolores de cabeza. Cada vez que por algún motivo (por ejemplo mantenimiento) debe apagar el servidor al arrancar trabaja desesperantemente lento y tarda casi una hora en empezar a trabajar normalmente.

leer más

por jcasano el 16 marzo 2012 06:11

29 febrero 2012

Rafael Martinez

Líneas de tiempo del proyecto PostgreSQL y las principales RDBMS

documentos

Hace ya un tiempo que empecé a trabajar en dos diagramas con las líneas de tiempo (timeline) del proyecto PostgreSQL y las principales bases de datos relacionales de la historia. Hoy me he decidido a publicarlos para que los interesados en el tema tengan esta información disponible.

leer más

por rafaelma el 29 febrero 2012 02:53

Nuevas versiones de PostgreSQL disponibles

postgres-logo

El proyecto PostgreSQL ha lanzado nuevas versiones menores de todas las series activas de PostgreSQL. Esta actualización arregla algunos problemas de seguridad.

Si utilizais pg_dump, certificados SSL y/o triggers que usen SECURITY DEFINER, deberiais de actualizar vuestros sistemas inmediatamente.

Las nuevas versiones disponibles son 9.1.3, 9.0.7, 8.4.11 y 8.3.18.

Anuncio oficial de este lanzamiento:
http://www.postgresql.org/about/news/1377/

Más información sobre las versiones lanzadas:
http://www.postgresql.org/docs/current/static/release.html

Descargas:

leer más

por rafaelma el 29 febrero 2012 08:18

28 febrero 2012

Samuel Zarza Fernandez

Orden y formato al código PL/pgSQL


“Any code of your own that you haven’t looked at for six or more months might as well have been written by someone else.”
Eagleson’s Law

Leer y entender un trozo de código de unas pocas líneas es fácil, aunque haya sido escrito como si se hubiese caído al suelo y esparcido por toda la habitación. Ahora bien, si tenemos que leer unos cuantos cientos o miles de líneas, la cosa cambia bastante. Es fundamental tener un código ordenado y bien identado para facilitar la legibilidad.

Existen muchas herramientas que facilitan o realizan directamente esta tarea. Son las llamadas herramientas de embellecimiento o formato ("code beautifiers/formatters tools"). La mayoría de los IDE's y editores tienen herramientas para una gran variedad de lenguajes... salvo para PL, donde me he encontrado bastantes carencias.

Si necésitáis una herramienta de este estilo, una de las mejores que me he encontrado es Pl/Sql tidy. Algunas de sus características son:
  • Identación por bloques
  • Compactación
  • Ajuste de mayúsculas/minusculas
  • Alineamiento vertical en asignaciones
El uso de la herramienta es a través de línea de comando, pero también podéis usar la interesante versión online disponible.

Funciona con PL/pgSQL.


Referencias y más información:

por Samuel Zarza Fernández (noreply@blogger.com) el 28 febrero 2012 03:14

24 febrero 2012

Jaime Casanova

Sobre la integridad del código

Acabo de leer un artículo (http://www.techweekeurope.co.uk/news/open-source-code-is-cleaner-than-proprietary-says-coverity-62518) referente a la calidad del código de proyectos open source en comparación con proyectos propietarios (privativos, aunque no es lo mismo propietario es el termino que se uso en el artículo).

leer más

por jcasano el 24 febrero 2012 04:17

04 febrero 2012

Rafael Martinez

Logs via SQL/MED

idea

Con la versión 9.1 de PostgreSQL tenemos disponible una nueva funcionalidad llamada SQL/MED mediante la cual se puede acceder a datos externos a nuestra base de datos mediante comandos SQL.

En SQL/MED existen los llamados "Foreign Data Wrapper (FDW)" que es una especie de "driver" para acceder a un tipo de datos externos. Existen diferentes tipos y con la versión 9.1 existe uno en los modulos contrib que se llama file_fdw. Este FDW se puede utilizar para acceder ficheros en formato CSV.

leer más

por rafaelma el 04 febrero 2012 01:49

20 enero 2012

Urko Benito Mateo

DBLink con parametros en PostgreSQL

Introducción
Hace unos días una persona me dejó una duda a modo de comentario en la entrada de DBLinks en PostgreSQL. Esta duda es sencilla, y, a la vez interesante, por eso, he decidido crear una entrada explicando la solución.

La duda
¿Es posible crear una vista en PostgreSQL utilizando un DBLink con parámetros dinámicamente?

Es decir, lo que queremos es hacer los siguiente:
SELECT device_name FROM remote_database_v(param1, param2);
La solución
Sobre si es posible crear una Vista con un DBLink parametrizado, lo cierto es que no se puede, es decir, no podemos crear una vista pasando un argumento.

Sin embargo, podemos crear un procedimiento que nos devuelva un tipo "record" y pasarle como parámetros la cadena de conexión, por ejemplo:
CREATE OR REPLACE FUNCTION test_dblink_with_parameter(dbname character varying, dbhost character varying, dbuser character varying, dbuserpass character varying)
  RETURNS SETOF record AS
$BODY$
    SELECT t.device_name
    FROM dblink('dbname=' || $1 || '  port=5432 host=' || $2 || ' user=' || $3 ||' password=' || $4 , 'SELECT device_name FROM devices.as_device') as
     t(device_name character varying);
$BODY$
  LANGUAGE sql VOLATILE;
Y ahora podemos llamar a nuestro procedimiento como si fuese una tabla o vista.

Recordar que al ser de tipo "record" tenemos que decirle cómo es el formato del registro <AS (field1 type, field2 type, fieldn type)>, en nuestor caso devuelve el campo "as_device" que es de type "character varying".
SELECT * FROM test_dblink_with_parameter('dbname','localhost','user','password') AS (device_name character varying);
Algunas Mejoras
En función de los datos que estamos obteniendo, podemos, por ejemplo, optimizar el coste <COST> y el número de rows <ROWS> del procedimiento. En el ejemplo, hemos dejado el coste y el número de rows "por defecto",  COST 100ROWS 100.

Referencias


por Urko Benito (noreply@blogger.com) el 20 enero 2012 11:35

12 enero 2012

Santiago Zararte

Create ISO image from USB/Pendrive or any directory || Crear una imagen ISO desde un Pendrive o cualquier directorio

If you ever have the need to create a ISO image from a Pendrive/USB disk or a directory, this line might save your life.

Si en algun momento te has visto en la necesidad de crear una imagen ISO de un pendrive, disco usb o un directorio en particular esta linea podria salvar tu vida:

mkisofs -o name-of-your-image.iso /path/to/directory 

And that’s it, no sudo, no dd, no need to use more space than needed (a problem i found using DD)
Y eso es todo, sin sudo, sin dd, sin necesidad de usar mas espacio del requerido (un problema que encontre cuando trate de usar dd)

note: add -J if you’re planning to use that iso on windows
nota: agrega -J si vas a utilizar esa ISO en windows

por foursixnine el 12 enero 2012 12:52

28 diciembre 2011

Santiago Zararte

Git repository from scratch | Creando un repositorio GIT desde cero

Just go to the end of the post if you dont wanna read all of it
So you’ve been playing with git, and you’ve already done the common thing:

$ git init
$ git add .
$ git commit

And then, you decide to upload your code somewhere else than github, gitorius or anywhat lets you use git (and where the workflow is: first create the repo, clone, then develop). That’s when you meet it, the hell… Its very annoying specially when you just want quick development, and what you really need is to start something, after you finish you decide to track the code, and then you see yourself in something like this:

$ mkdir ../myproject-new
$ cd ../myproject-new
$ git init
$ mv ../myproject/* .
$ git add .
$ git commit

And then, you meet the unconfortable truth, you dont have a bare rep to push your changes… so you kind of start over, to create a new repo so you can clone from it (although its empty) then add your files, commit and push… An easy way to do this would be like this:

Say you have a local branch, no other locations to pull from or to push to, your only working copy, and want to upload somewhere… before going into the git init|add|commit|clone|add origin hell just do this within your working copy:

git clone --bare $(pwd) git://server.com/path.git

And that’s it, this will create a new bare directory under the the path you specified… with no additional setup, and no madness. So you can ask your team members to just clone from server.com/path.git and that’s it… Painless

por foursixnine el 28 diciembre 2011 07:53

MD5 easily from shell with Perl | MD5 Facil desde la consola con Perl

Recently i found myself having to generate a md5 hash to specific lines in a file… after googling a while (being addicted to automation more than repeating myself) i came with this simple solution in perl:

perl -M'Digest::MD5 qw(md5_hex)' -e 'print md5_hex("`date +%d%m%y`")'
view raw md5.sh This Gist brought to you by GitHub.

por foursixnine el 28 diciembre 2011 07:35

Pretty Print JSON | Mostrando cadenas en JSON Legibles

This is a post of the series: How I.
Este es un post simple en la serie “Como yo“.

The idea for now is to show JSON strings in a fashion way so that we can read complex JSON strings easier, ill show some ways, its up to you which one to use.

La idea es poder ver cadenas JSON en una forma bonita y sencilla de leer complejas cadenas JSON, de una forma realmente sencilla. Mostrare algunas formas, tu decides cual te conviene.

Python:

cat file.json | python -mjson.tool

Perl:

cat file.json | perl jsonpp.pl
#!/usr/bin/env perl

use JSON;

my $json = JSON->new;
undef $/;
while (<>) {
    print $json->pretty->encode($json->decode($_));
}
view raw jsonpp.pl This Gist brought to you by GitHub.

ps: Most of the info comes from a post at endpoint’s blog

por foursixnine el 28 diciembre 2011 07:24

23 diciembre 2011

Rafael Martinez

Creando 30.000 tablas con PostgreSQL

cpu

Esta mañana leyendo los mensajes de Twitter que me llegaron por la noche, me encontre con uno que me llamó la atención, "Steward Smith blogs on Optimazing InnoDB for creating 30.000 tables (and nothing else)".

Empece a leerlo y estuvo entretenido. Trataba de lo que se podia hacer para acelerar la creación de muchos objetos en MySQL usando InnoDB, esto es especialmente importante cuando se vaya a importar una nueva base de datos que sea grande.

leer más

por rafaelma el 23 diciembre 2011 02:15

06 diciembre 2011

Rafael Martinez

Nuevas versiones de PostgreSQL disponibles

postgres-logo

El proyecto PostgreSQL ha lanzado nuevas versiones menores de todas las series activas de PostgreSQL. Las nuevas versiones disponibles son 9.1.2, 9.0.6, 8.4.10, 8.3.17 y 8.2.23. Recordamos que la serie 8.2 no se actualizará más y la versión 8.2.23 es la última versión de esta serie.

Anuncio oficial de este lanzamiento:
http://www.postgresql.org/about/news/1366/

Más información sobre las versiones lanzadas:
http://www.postgresql.org/docs/current/static/release.html

Descargas:
http://www.postgresql.org/download/

Código fuente:
http://www.postgresql.org/ftp/source/

leer más

por rafaelma el 06 diciembre 2011 12:33

14 noviembre 2011

Samuel Zarza Fernandez

Los niveles de aislamiento en PostgreSQL (no son 4)



"No. No lo intentes. Hazlo, o no lo hagas, pero no lo intentes."

Cuando ví el Episodio IV de la Guerra de las Galaxias ("El Imperio Contraataca"), aún era un niño impresionable, y me llamó la atención la reprenda que hizo Yoda a Luke y que cito aquí. Era uno de ésos consejos marciales que se enuncian solemnes como un consejo vital.

Con el tiempo te das cuenta que como consejo está bien, y puede ser incluso un buen objetivo... pero en ciertas facetas de la vida no es válido. Por ejemplo, en el mundo científico y en nuestro mundo profesional el consejo es justamente el contrario: inténtalo, pruébalo y compruébalo. Y sólo cuando lo hayas hecho y consigas un resultado repetible, ponlo en práctica, esto es, súbelo a producción.

Gracias a no seguir el consejo de Yoda fui consciente de una (grave) carencia de PostgreSQL con respecto a los niveles de aislamiento. Como ya hice una introducción al aislamiento en otro artículo, no voy a extenderme más en el tema y voy al grano. El caso que me ocupaba es que tenía que hacer una importación transaccional de datos masiva en un sistema en OLTP de producción en el que se están modificando constantemente datos relacionados con los que voy a importar. El resultado de la importación es que la transacción gigante bloquea datos e impide que se efectúen modificaciones en datos relacionados paralizando en la práctica buena parte de las operaciones de producción produciéndose un efecto "bola de nieve" al sumarse cada vez más transacciones en cola a la transacción gigante pendiente. Sin embargo, para lo único que quiero la transacción es para tener atomicidad en la operación, es decir, para que no se quede a medias en caso de algún problema, pero no me importa que se puedan producir eventualmente casos de dirty read, que no afectarían a los usuarios del sistema de producción en su trabajo. Vale, no hay problema. La transacción de inserción la podemos realizar con el nivel de aislamiento más bajo (READ_UNCOMMITED) y problema solucionado. ¿No? No obstante, no hagamos caso a Yoda, y probémoslo en pre-producción. Resultado: exactamente el mismo que si no hubiera especificado nada del nivel de aislamiento.

¿Qué ha pasado?

En la documentación de SET TRANSACTION, en efecto compruebo que PostgreSQL admite los cuatro niveles de aislamiento como la mayoría de las bases de datos (de hecho, la sentencia no dio error)... pero sólo sintácticamente: no están todos implementados. Si contiúas leyendo te das cuenta que no son 4, sino 2 los niveles implementados:
"The SQL standard defines two additional levels, READ UNCOMMITTED and REPEATABLE READ. In PostgreSQL READ UNCOMMITTED is treated as READ COMMITTED, while REPEATABLE READ is treated as SERIALIZABLE."
Lo que viene a decir: "¿Pensabas que eran cuatro, no? Pues no. Son dos". De hecho, ahora (con la versión 9.1) ya son 3. Pero sigue sin estar soportada la lectura sucia (dirty read). En la documentación sobre aislamiento también es bastante claro:
"In PostgreSQL, you can request any of the four standard transaction isolation levels. But internally, there are only two distinct isolation levels, which correspond to the levels Read Committed and Serializable. When you select the level Read Uncommitted you really get Read Committed, and when you select Repeatable Read you really get Serializable, so the actual isolation level might be stricter than what you select."

Un verdadero jarro de agua a mis pretensiones, ya que no puedo conseguir atomicidad sin bloqueo (aunque sea realizando lecturas de transacciones no confirmadas) en PostgreSQL, al menos con la versión actual 9.1.


Referencias y más información:

    por Samuel Zarza Fernández (noreply@blogger.com) el 14 noviembre 2011 12:17

    01 noviembre 2011

    Samuel Zarza Fernandez

    Alternativas EAV con XML (en PostgreSQL 8.3)

    El modelo EAV
    El modelo Entidad-Atributo-Valor (EAV, Entity-Attribute-Value), también conocido como Objeto-Atributo-Valor o Esquema Abierto, se usa en casos donde el número de atributos (propiedades, parámetros) usados para describir una entidad u objeto es potencialmente grande, pero que aplicados individualmente a una entidad concreta es pequeño. Las circunstancias donde se suelen aplicar son:
    • Entidades con atributos heterogéneos:
      • Entidades dinámicas en el tiempo, donde los atributos de una entidad son fijos, pero durante un período de tiempo variable. Es decir, son cambiantes (pueden crecer o decrecer) en el tiempo.
      • Entidades conceptualmente dinámicas, dependiendo de la interpretación del sistema en un determinado momento. Es decir, entidades cuyo número de atributos cambia según el contexto (p.e.: atributos definidos por el usuario)
    • Entidades con atributos homogéneos muy poco densos. Es decir, entidades con una desproporción muy grande entre el número de atributos posibles y el número de atributos con valor (no nulos).
    Entidades en escenarios típicos de este tipo de modelos son, por ejemplo:
    • documentos (en una base de datos documental) cuyos atributos asignados a cada documento depende de la empresa, departamento, tipo de documento, etc...
    • información cuya catalogación adicional depende de parámetros definidos por el usuario
    • conceptos de negocio o abstractos cuyos atributos dependen de varios factores y varían en el tiempo: "expediente", "valoración", "indicencia", etc...
    Este modelo se suele resolver sobre el modelo relacional con tres tablas: la de entidad, la de atributos posibles de dicha entidad y la de valores. La información se registra conceptualmente en la tabla de valores, que relaciona la información a través de tres columnas: clave ajena de entidad, clave ajena de atributo y valor.

    Incidencia
    Id Fecha
    1 17/05/19 22:10
    2 18/05/19 10:13
    3 18/05/19 17:05
    Datos
    Id NombreAtributo
    1 Longitud
    2 Temperatura
    3 Volumen
    4 Sector
    DatosIncidencia
    IdInc IdDato Valor
    1 1 5
    1 4 A
    2 2 6
    2 3 4
    2 4 A

    Los problemas que aporta este modelo son:
    • Consultas SQL complejas (muchos "CASE"), que en algunos casos deben usar herramientas típicas de datawarehouse (PIVOT, crosstab, etc), para convertir en columnas lo que, en realidad, son filas.
    • Tipo de dato único para todos los atributos, sean numéricos, fechas o cadenas, que luego deberán convertirse, o complicar el modelo con distintas tablas de atributos en función del tipo de dato.

    XML y Xpath al rescate
    Una buena alternativa a este tipo de problemas es implementar un campo con XML y procesarlo con herramientas XPath. Lamentablemente, el tipo de dato XML de PostgreSQL 8.3 aún no tiene operadores de comparación ni se pueden crear índices sobre este tipo de dato, pero se puede tratar como String y indexar expresiones XPath como veremos a continuación.

    La ventaja de usar XML es que podemos contar con un número de atributos variable encapsulados en un documento XML en un sólo campo y evitar tener que usar el modelo EAV, por ejemplo:  

    Incidencia
    Id Fecha DatosIncidencia
    1 17/05/19 22:10 <data><longitud>5</longitud><sector>A</sector></data>
    2 18/05/19 10:13 <data><temperatura>5</temperatura><volumen>4</volumen><sector>A</sector></data>
     
    Con una tabla como la anterior, podemos realizar consultas sencillas con XPath, tipo
    SELECT xpath('/data/temperatura/text()', DatosIncidencia)
    FROM incidencia
    que nos permite un control total en la consulta de atributos sin complicadas consultas. Puede haber quien le parezca que XPath es complicado y que no se gana tanto, pero en mi opinión, es más sencillo tratar con un único campo y una única tabla aunque tengamos que realizar un pequeño aprendizaje de XPath. A la larga, todo es más simple: tanto las consultas como el mantenimiento.

    También se pueden optimizar ciertas consultas comunes creando índices, aunque usando algún truco.

    El soporte de XML "de serie" en PostgreSQL no ha hecho más que empezar, y le queda un gran camino por recorrer, pero ya estamos en disposición de empezar a aprovecharlo.


    Referencias y más información:

    por Samuel Zarza Fernández (noreply@blogger.com) el 01 noviembre 2011 09:14

    07 octubre 2011

    Rafael Martinez

    ¿Dónde están nuestros datos en el disco?

    servidor

    Acabo de publicar un artículo sobre como PostgreSQL graba y organiza nuestros datos en el disco. Una introducción a un tema que todo administrador de bases de datos deberia saber algo sobre el mismo.

    El artículo se titula "¿Dónde están nuestros datos en el disco?" y está disponible en http://www.postgresql.org.es/node/667

    --
    Rafael Martinez Guerrero
    PostgreSQL-es

    por rafaelma el 07 octubre 2011 10:06

    26 septiembre 2011

    Rafael Martinez

    Nuevas versiones de PostgreSQL disponibles

    postgres-logo

    El proyecto PostgreSQL ha lanzado nuevas versiones menores de todas las series activas de PostgreSQL. Las nuevas versiones disponibles son 9.1.1, 9.0.5, 8.4.9, 8.3.16 y 8.2.22. Recordamos que la serie 8.2 dejará de actualizarse a partir de noviembre 2011.

    Anuncio oficial de este lanzamiento:
    http://www.postgresql.org/about/news.1355

    Más información sobre las versiones lanzadas:
    http://www.postgresql.org/docs/current/static/release.html

    Descargas:
    http://www.postgresql.org/download/

    Código fuente:
    http://www.postgresql.org/ftp/source/

    Instalador fácil:

    leer más

    por rafaelma el 26 septiembre 2011 07:36

    24 septiembre 2011

    Urko Benito Mateo

    Cómo clonar una tabla en PostgreSQL

    Introducción
    Alguna vez hemos necesitado clonar una tabla, tanto estructura como contenido desde el propio SQL sin tener que recurrir a <pg_dump>.
    Tal vez alguno esté pensando en un CREATE TABLE AS SELECT ... pero lo cierto es que esta solución no nos crea los modificadores, índices, etc.

    Sin embargo, no os preocupéis, que en PostgreSQL se puede hacer todo, o casi, y este caso sí que está muy resuelto.

    Pasos Ejemplo de Clonado "completo"
    A continuación os muestro -de una forma sencilla- lo que vamos a hacer, paso a paso para que no resulte complicado:
    1. Crearemos una tabla llamada test con los campos company y homepage
    2. Añadiremos un índice único en company
    3. Añadiremos un par de compañías
    4. Crearemos una tabla nueva copiando el contenido de la tabla con un CREATE TABLE  AS SELECT para comprobar cómo no clona los índices, defaults, etc.
    5. Utilizaremos un clonado completo
    Una vez explicado, vamos a ponernos manos a la obra

    search=> CREATE TABLE test(company VARCHAR(20) NOT NULL, homepage VARCHAR(40) NOT NULL);
    CREATE TABLE
    search=> CREATE UNIQUE INDEX test_company_uq ON test(company);
    CREATE INDEX
    search=> \d test
                 Table "public.test"
      Column  |         Type          | Modifiers
    ----------+-----------------------+-----------
     company  | character varying(20) | not null
     homepage | character varying(40) | not null
    Indexes:
        "test_company_uq" UNIQUE, btree (company)

    Ahora, añadimos un par de registros
    search=> INSERT INTO test(company,homepage) VALUES('SFChildren', 'http://www.sfchildren.com');
    INSERT 0 1
    search=> INSERT INTO test(company,homepage) VALUES('HavocTec', 'http://www.havoctec.com');
    INSERT 0 1
    search=> SELECT * FROM test;
      company   |         homepage         
    ------------+---------------------------
     SFChildren | http://www.sfchildren.com
     HavocTec   | http://www.havoctec.com
    (2 rows)
    Copiamos su contenido utilizando CREATE TABLE newTable AS SELECT * FROM sourceTable y comprobaremos su resultado
    search=> CREATE TABLE test2 AS SELECT * FROM test;
    SELECT
    search=> \d test2
                 Table "public.test2"
      Column  |         Type          | Modifiers
    ----------+-----------------------+-----------
     company  | character varying(20) |
     homepage | character varying(40) |
    Como podemos observar, lo primero que nos falta es el índice que hemos creado <test_company_uq> y los modificadores <NOT NULL> en ambos campos.

    Es decir, utilizando esta forma copiamos el contenido y estructura de campos pero no sus modificadores, pero, que no cunda el pánico, vamos a ver cómo lo podemos hacer de una forma sencilla.

    Borramos la tabla test2 que hemos creado para poder volver a clonarla, esta vez de forma completa.
    search=> DROP TABLE test2;
    DROP TABLE


    Clonar "todo", para ello vamos a utilizar los modificadores LIKE tabla INCLUIDING [DEFAULTS | CONSTRAINTS | INDEXES]. En nuestro ejemplo, queremos "clonar" toda la estructura  así que utilizamos todas.
    search=> CREATE TABLE test2 (LIKE test INCLUDING DEFAULTS INCLUDING CONSTRAINTS INCLUDING INDEXES);
    CREATE TABLE
    search=> \d test2
                 Table "public.test2"
      Column  |         Type          | Modifiers
    ----------+-----------------------+-----------
     company  | character varying(20) | not null
     homepage | character varying(40) | not null
    Indexes:
        "test2_company_key" UNIQUE, btree (company)
    Conclusiones
    Aunque el ejemplo es sencillo, la idea era mostrar la potencia de la opción LIKE ... INCLUIDING sin tener que mostrar una estructura muy compleja.

    Además, para aquellos que no os guste el SQL, siempre podéis utilizar el comando <pg_dump> para exportar una tabla.


    Referencias

    por Urko Benito (noreply@blogger.com) el 24 septiembre 2011 11:46

    16 septiembre 2011

    Jaime Casanova

    PGDay Ecuador 2011

    Por primera vez en Ecuador se realizará un PGDay. ¿Pero que es un PGDay y por qué deberíamos hacer uno?

    leer más

    por jcasano el 16 septiembre 2011 12:02

    12 septiembre 2011

    Jaime Casanova

    PostgreSQL 9.1 ha sido liberado

    12 de Septiembre del 2011: El Grupo Global de Desarrollo de PostgreSQL anuncia el lanzamiento de PostgreSQL 9.1. Esta nueva versión de la bases de datos de código abierto líder ofrece tecnología innovadora, extensibilidad sin igual, y nuevas características como replicación sincrónica, método de indexado "K-Nearest Neighbor", and conectores de datos foráneos.

    leer más

    por jcasano el 12 septiembre 2011 03:53

    Rafael Martinez

    Lanzamiento de PostgreSQL 9.1

    postgres-logo

    Hoy se lanza una nueva versión principal de PostgreSQL, la versión 9.1. Después de un año de desarrollo y pruebas, este lanzamiento trae muchas características nuevas y potentes.

    A continuación teneis un resumen de la nota de prensa oficial. El documento completo lo teneis en http://www.postgresql.org/about/press/presskit91.html.es

    leer más

    por rafaelma el 12 septiembre 2011 12:59

    25 agosto 2011

    Jaime Casanova

    Revista PostgreSQL

    En Mayo de este año se lanzo la edición # 00 de pgmag que es la primera revista exclusivamente sobre PostgreSQL.
    En realidad eso fue solo una prueba, que al parecer ha sido exitosa con mas de 4000 descargas de la página y se ha repartido en varios eventos.

    Ha decir verdad, pensaba anunciarla por aqui pero esperaba a que se terminará la traducción al español que aparentemente no termino Sad

    leer más

    por jcasano el 25 agosto 2011 11:03

    18 julio 2011

    Jaime Casanova

    Auditoría de tablas

    ¿Con qué frecuencia se le ha pedido a alguno de ustedes que se registren todos los cambios de las tablas para auditoria? AFAIR, todos y cada uno de los clientes que he tenido me ha pedido esto

    Hasta ahora, he usado table_log (http://pgfoundry.org/projects/tablelog) para eso, pero eso esta lejos de ser una solución ideal por varias razones.

    leer más

    por jcasano el 18 julio 2011 07:36

    14 julio 2011

    Jaime Casanova

    Segundo día del CHAR(11)

    Como comente en el artículo anterior de este blog, el 11 y 12 de Julio se realizó la conferencia CHAR(11). Y al igual que el lunes 11, el programa del martes 12 fue impresionante. Así que aprovechare el viaje en tren a Londres para comentarles un poco lo que pasó.

    leer más

    por jcasano el 14 julio 2011 08:33

    12 julio 2011

    Jaime Casanova

    Primer día del CHAR(11)

    El día de ayer, 11 de Julio, dio inicio a la conferencia denominada CHAR(11) (un interesante uso de siglas para Clustering, High Availability and Replication).

    leer más

    por jcasano el 12 julio 2011 08:37