viernes 20 de enero de 2012

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


lunes 2 de enero de 2012

Feliz 2012

Hemos pasado un año más, y como siempre, toca hacer un repaso a los 365 días que han transcurrido con sus buenos y malos momentos.

Puedo decir que para mi el 2011 ha sido uno de los años más gratificantes -tanto personal como profesionalmente- y, espero que el 2012 sea aún mejor.

Comencé una nueva aventura en Havoc Technologies como responsable del área de I+D e IT, todo un desafío, pero, ya estamos en la rampa de salida con los productos de Navegación Segura para Niños y Sistemas de Control de Navegación para empresas.

Todo ello basado en Solaris, PostgreSQL y Hadoop. Tecnologías que me encantan, y, aunque los comienzos no fueron fáciles, ya estamos a pleno rendimiento!

Por ello, me gustaría desear a todos los SysAdmins un Feliz 2012


Un Saludo,
Urko

jueves 15 de diciembre de 2011

Cómo ver el porcentaje de iNodes Libres y Usados en OpenIndiana

Introducción
Alguna vez os ha pasado encontrar en el syslog el mensaje de "out of inodes", si nunca lo habéis encontrado mejor :D.

El problema viene porque el sistema de ficheros se está quedando -o se ha quedado sin inodes libres- y no puede crear/modificar los archivos que contiene ese FileSystem.

Principalmente me he encontrado con este problema cuando parametrizaba un servidor de cache squid con unos valores muy elevados de L1 y L2 en cache_dir y la unidad no era lo suficientemente grande.

Simplemente deberemos utilizar la opción <-i> del comando </usr/gnu/bin/df> de GNU ya que Solaris no lo incluye, por ejemplo:
havoc@hseries:~$ df -i /
Filesystem         Inodes   IUsed   IFree IUse% Mounted on
rpool/ROOT/solaris 861385   593804  86079 1%    /

Referencias

domingo 30 de octubre de 2011

Cómo desactivar ACPI en OpenIndiana

Introducción
OpenIndiana incluye soporte para el sistema ACPI, sin embargo, en algunas ocasiones, puede que nuestro sistema no pueda iniciarse correctamente, y debamos desactivarlas.

Para poder desactivar el sistema ACPI debemos utilizar la opción <acpi-user-options=MODO> en nuesto menú de arranque grub en la sección de <kernel>, donde "modo" será uno de los siguientes valores:
  • acpi-user-options=8, Desactiva el nuevo sistema ACPI y deja el sistema en formato "Legacy".
  • acpi-user-options=4, Desactiva el nuevo y sistema "Legacy" aunque permite seguir definiendo los Threads de los micros HyperThread a traves de ACPI.
  • acpi-user-options=2, Desactiva todo el ACPI por completo.
Deberemos utilizar las opciones de mayor a menor -8,4,2- si encontramos problemas en nuestro OpenIndiana.


Por ejemplo, si queremos poner la opción de "desactivado por completo" en la entrada "HSeries", editaremos el archivo /rpool/boot/grub/menu.lst de la siguiente forma:
havoc@h1master:~$ pfexec vi /rpool/boot/grub/menu.lst
title HSeries

findroot (pool_rpool,0,a)
bootfs rpool/ROOT/hseries
kernel$ /platform/i86pc/kernel/$ISADIR/unix -m verbose -B $ZFS-BOOTFS,acpi-user-options=2
module$ /platform/i86pc/$ISADIR/boot_archive
Conclusión
Alguna vez podemos encontrarnos con problemas de arranque de OpenIndiana -sobre todo en VMWare ESX- que se solucionan en la mayoría de los casos poniendo la opción de ACPI a 2

Referencias

sábado 24 de septiembre de 2011

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