Grimpi IT Blog

abril 22, 2011

Como migrar una base de datos de SQL Server a PostgreSQL

Filed under: Migrador, PostgreSQL, SQL Server — grimpi @ 11:20 pm

Hace poco tuve que migrar varias bases de datos de SQL Server a PostgreSQL 8.4. Si bien existen varias maneras de hacer esto, no encontré ninguna herramienta fiable y gratis que me permita realizar esta operación. Por supuesto que si estamos dispuestos a pagar, existen utilidades de conversión de bases de datos y algunas muy buenas. Pero gratis, nada que funcione decentemente. Por lo tanto, aprovechando bastante código que ya tenía escrito para otra cosa, decidí hacer mi propio conversor de bases de datos de SQL Server 2005/2008 a PostgreSQL 8.4, que subo para que cualquiera la pueda probar y ahorrarse tiempo y dinero. La aplicación es muy sencilla: ingresamos el connection string de la base de datos de SQL Server y presionamos el botón “Generar Script”. Esto va a generar un codigo SQL en la caja de texto de la aplicación que deberemos copiar y ejecutarlo en algún lugar.

Qué cosas migra este utilitario?
• Schemas
• Tablas
• Constraints (Primary Keys, Unique Keys, Foreign Keys)
• Indices
• Tipos de datos (Domains en PostgreSQL)
• Vistas (Si el código SQL utilizado es compatible con PostgreSQL, no vamos a tener problemas, de lo contrario, tendremos que modificarlo manualmente para hacerlo compatible).
• Comentarios (Extended Properties en SQL Server)

Qué cosas no migra?
• Datos (para eso podemos utilizar algún ETL o SSIS)
• Store procedures/funciones/triggers (La aplicación sin embargo, nos permite generar el script de estos objetos, para que luego los modifiquemos manualmente).

Adicionalmente, este utilitario agrega un par de funciones que existen en SQL Server y no en PostgreSQL como por ejemplo “newid()”, cuando usamos columnas tipo ROWGUID en SQL Server.
También se genera un trigger automáticamente, cuando existe una columna Computed, ya que esta feature no existe en PostgreSQL. Tiene una mínima inteligencia en algunos aspectos, que nos pueden ahorrar mas tiempo todavía. Por ejemplo, cuando encuentra que se llama a la función GetDate(), se reemplaza por su homologa en PostgreSQL que es now(). Lo mismo hago para DatePart y un par de funciones mas.

Esta aplicación es muy básica, pero potente. No garantizo que funcione en todos los escenarios ni que sea infalible. Pero me ha servido para convertir bases de datos muy complejas de manera muy rapida y creo que puede servir a muchos.

La aplicación se puede bajar de esta URL.

Toda sugerencia, queja, critica sera bievenida.

abril 5, 2011

¿El desarrollo de software hoy en día es más productivo que hace 10 años atrás?

Filed under: Opinion — grimpi @ 3:20 pm

La primera aplicación que hice en mi vida profesional, fue una típica intranet para una empresa. Todo el código y acceso a la base de datos, se ejecutaba en archivos ASP.
Luego me dijeron que está mal acceder directamente a las tablas de la base de datos desde el código, por lo tanto implemente store procedures para cada uno de los accesos a la base.
Luego me dijeron que está mal mezclar lógica de negocio y de presentación en el mismo archivo, por lo que implemente la lógica de la aplicación en un componente que era llamado por el ASP.
Luego me dijeron que con eso no alcanza, que hay que dividir la lógica de la aplicación en acceso a los datos y en reglas de negocio, por lo que tuve que crear 2 clases para trabajar con una entidad. Una que acceda a los datos y otra que tenga las reglas de negocio.
Luego me dijeron que había que implementar mecanismos de logueo de excepciones, por si ocurre algún error inesperado. Por lo tanto debíamos utilizar algún framework de logging (porque grabar texto en un archivo x DIA, es algo que requiere un framework).
Luego me dijeron que está mal instanciar directamente el framework de logging desde los componentes, que debíamos abstraerlo a una interfaz, por si el DIA de mañana cambiamos de framework.
Luego me dijeron que está mal tener toda la capa de presentación en solo archivo. Hay que usar el patrón MVC y tener un archivo de vista con el código HTML, una clase controller que maneje el flujo y comportamiento y otra clase modelo. Para eso, debería usar algún framework MVC.
Luego me dijeron que los store procedure son obsoletos, que esta mal poner lógica de negocio en la base de datos y que si el DIA de mañana migramos de base de datos vamos a tener problemas, por lo tanto, debería usar algún framework ORM y crear un archivo XML por entidad que mapee las clases con los datos.
Luego me dijeron que está mal subir todo esto directo manualmente a producción, por lo tanto, deberíamos configurar algún mecanismo de integración continua que baje los archivos del repositorio de fuentes, los compile, ejecute los test de integración y los suba a un FTP o los copie a un directorio. Para esto debíamos crear un archivo de compilando en NANT o MSBUILD o similar.
Luego me dijeron que por cada método que tenemos, hay que hacer test unitarios para verificar que algún nuevo cambio, no rompa el código, por lo tanto, hay que crear una nueva clase de testing por cada clase de negocio, usando algún framework de test unitario.
Luego me dijeron que ejecutar pruebas unitarias que accedan a la base de datos esta mal y es muy lento, por lo cual deberíamos utilizar algún framework de mocking que “simule” este comportamiento, por lo tanto, debíamos modificar los constructores de nuestras clases para que acepten inyección de dependencias y debíamos crear una interfaz por cada clase “mockeable”. Sin embargo, debíamos mantener nuestros antiguos test unitarios que accedían a la base que ahora pasan a llamar test de integración, porque necesitamos una prueba integrada con el resto de los componentes del sistema. Entonces por cada método, ahora debemos crear 2 tipos de test, el unitario y el de integración.
Luego me dijeron que no había razón alguna para utilizar “manualmente” inyección de dependencias existiendo frameworks que hagan esta tarea tan difícil y complicada (sic).
Luego me dijeron que autenticar nuestro usuario directamente contra la base de datos o un servidor Active Directory/LDAP es antiguo e inseguro. Ahora hay que utilizar algún mecanismo de autenticación por claims moderno, seguro y ágil. Por lo tanto, debíamos utilizar algún framework de autenticación como WIF.

Para crear un ABM de clientes, pasé de tener un simple archivo ASP (o ASPX, o JSP) a tener que crear un archivo HTML, una clase model, una clase controller, una clase repository de acceso a datos con su respectiva interface, una clase service que maneje la lógica de negocio con su respectiva interface, una clase para test unitarios, otra clase para test de integración, aprender a utilizar (como mínimo y básico) un framework MVC, ORM, de Unit Testing, Mocking, de inyección de Dependencias y de autenticación. También debemos crear varios archivos XML de configuración para los distintos frameworks. Por supuesto no hay que olvidarse que debemos también crear clases e interfaces adicionales para los distintos patrones de diseño existentes que hacen nuestro código más elegante, óptimo, lindo, portable, legible, etc. O sea, más PRO.
Todo para mejorar la productividad y velocidad en el desarrollo de aplicaciones. Todo para que el “desarrollador no pierda tiempo en programar aspectos secundarios de la aplicación y se concentre en lo mas importante, que es la lógica de negocio.”.

No se ustedes, pero a mi este ciclo de evolución del desarrollo de software me parece que esta muy alejado de la palabra “productividad”.



abril 1, 2011

Habilitar/Deshabilitar una columna Identity de manera optima

Filed under: Identitys, SQL Server — grimpi @ 8:45 pm

En este post habíamos explicado como habilitar/deshabilitar la propiedad identity de una tabla en SQL Server. Habíamos visto que no existe un comando natural que haga esta tarea (algo así como un ALTER TABLE Cliente ALTER COLUMN ClienteId SET IDENTITY ON/OFF) y por lo tanto, no quedaba otra opción que reconstruir manualmente la tabla entera copiando los datos, con el enorme costo que esto representa.
Sin embargo, existe una forma alternativa, que si tenemos SQL Server 2005/2008 (solo en la edición Developer y Enterprise), podríamos utilizar. Esta solución en consiste en utilizar las opciones de particionamiento que se incorporaron en SQL Server 2005 para mover datos , en vez de utilizar el metodo clasico de reconstrucción de la tabla.
Veamos un ejemplo:

/*Creamos una tabla Paises de ejemplo con el campo row_id con la propiedad IDENTITY habilitada*/
CREATE TABLE dbo.Paises (row_id INTEGER IDENTITY PRIMARY KEY NOT NULL, data SQL_VARIANT NULL);
GO

/*Insertamos información de ejemplo*/
INSERT dbo.Paises (data)
VALUES (‘Argentina’), (‘Brasil’), (‘Chile’), (‘Uruguay’)
GO

/*Paso 1: Borro todos los objetos dependedientes de la tabla a modificar*/
ALTER TABLE ClienteAsociadoAPais DROP CONSTRAINT Paises_Original_FK

/*Paso 2: Creamos una tabla idéntica a la tabla Paises, pero sin la propiedad identity sobre la columna row_id.*/
CREATE TABLE dbo.Destination (row_id INTEGER PRIMARY KEY NOT NULL, data SQL_VARIANT NULL);

/*Paso 3: Movemos el contenido de una tabla a otra.*/
ALTER TABLE dbo.Paises SWITCH TO dbo.Destination;

/*Paso 4: Eliminamos la tabla original (que ahora no tiene datos).*/
DROP TABLE dbo.Paises;

/*Paso 5: Renombramos la tabla para que tenga el nombre original*/
EXECUTE sp_rename N’dbo.Destination’, N’Paises’, ‘OBJECT’;

/*Paso 6: Creo todos los objetos dependedientes de la tabla a modificada que habia borrado en el paso 1*/
ALTER TABLE ClienteAsociadoAPais ADD CONSTRAINT Paises_Original_FK

La clave de esto esta en la sentencia SWITCH, que en realidad no mueve datos, sino que simplemente cambia el puntero de datos de un lugar a otro, con lo cual nos ahorramos un montón de problemas relacionados con lockeos. Este método tiene enorme ventajas por el método que anteriormente habíamos visto en el post anterior. En tabla muy grandes, la diferencia de performance es enorme.
Veamos los siguientes números capturados del profiler, para la tabla ejemplo con varios millones de registros:

Metodo clasico de reconstruccion de tabla:

Duracion CPU Reads Writes
3,856,785 719 115,957 396

Metodo alternativo usando SWITCH:

Duracion CPU Reads Writes
259 140 519 2

Como se puede ver, no hay comparacion posible entre ambos metodos, en tablas de mucho volumen.

Sin embargo, hay un par limitaciones:

  • Esto solo funciona en las versiones Developer y Enterprise de SQL Server, ya que son las únicas que permiten manejo de particiones de tablas.
  • La tabla Destino debe tener exactamente la misma estructura que la tabla origen (con excepción obviamente de la propiedad identity sobre la columna).

Algo que hay que tener en cuenta, es que al igual que el método de reconstrucción de tabla, hay que borrar y crear nuevamente todas las foreign key asociadas a la tabla.

Links relacionados:
Partitioned Tables and Indexes

Crea un blog o un sitio web gratuitos con WordPress.com.