Optimizar la transformación Sort en SSIS

Uno de las tareas habituales a realizar con SSIS, suele ser la fusión de tablas que hubiesen sido particionadas horizontalmente en una única tabla. No estoy hablando de desnormalización, sino de los típicos casos en los que nos encontramos con una base de datos OLTP en la que por ejemplo, las transacciones comerciales de cada año han sido fraccionadas en diversas tablas. Para unir estos fragmentos, tenemos la transformación "Merge". El problema de la "Merge", es que requiere que ambas fuentes de datos se encuentren ordenadas con respecto a la misma clave. Aquí es donde surge la tentación de usar previamente la transformación Sort para ordenar estas fuentes.

¿Qué tiene de malo el uso de la Sort en estos casos? La Sort realiza la ordenación de los datos en la memoria del equipo que ejecuta SSIS… y esto puede ser bueno, o malo, según sea el origen de los datos. Supongamos que partimos de dos archivos de texto que contienen los datos desordenados… evidentemente, la Sort es una excelente opción en estos casos, ya que nos ordenará eficientemente los archivos (eso sí, a costa de un elevado consumo de memoria en el equipo que ejecuta SSIS). Sin embargo, ¿qué pasa si los datos vienen de tablas en una base de datos relacional? Alguno pensará que resulta un poco ridículo ordenar los datos en memoria, ¡cuando con una sentencia ORDER BY de SQL ya podemos traernos los datos ordenados! Quien haya pensado eso, está en lo cierto. Sin embargo, aunque traigamos los datos ya ordenados, la sentencia Merge se empeña en repetirnos una y otra vez que debemos usar la Sort. ¿Cómo podemos resolver este desaguisado?

Atentos a este truco del almendruco:

  1. Lo primero es traerse los datos ya ordenados de la base de datos. Para eso, recordad que cuando partimos de una fuente OLEDB, nunca es conveniente leer directamente de una tabla. Siempre es preferible utilizar una sentencia SQL en la que:
    • Nos traigamos únicamente los datos que necesitamos. Esto significa que sólo debemos traer a SSIS las columnas necesarias y la partición horizontal que necesitemos (si tenemos en una tabla las tallas de zapatos de nuestros futbolistas favoritos, y queremos obtener la lista de jugadores que calzan un número mayor que 42, haremos "SELECT DNI, Nombre, Apellidos, TallaZapato FROM Jugadores2003 WHERE TallaZapato > 42", NUNCA nos traeremos la tabla Jugadores completa). Esto hará que se reduzca el ancho de banda necesario para traernos los datos, y que al procesar menor volumen de datos en SSIS, éste pueda aprovechar de una forma más eficiente los buffers.
    • Usaremos la ORDER BY de SQL para ordenar los datos: "SELECT DNI, Nombre, Apellidos, TallaZapato FROM Jugadores2003 WHERE TallaZapato > 42 ORDER BY DNI". Por supuesto, ¡convendría que los datos estuviesen indexados en la base de datos con respecto a ese criterio!
    • Haremos lo mismo con el resto de tablas que queramos fusionar (en nuestro ejemplo, la tabla Jugadores2004).
  2. Aquí es donde empieza la parte interesante: haremos click con el botón derecho en las fuentes de datos, y seleccionaremos "Advanced options". En el nuevo diálogo que nos sale,  seleccionaremos "Input and output properties". En el árbol correspondiente, seleccionamos la salida estándar del nodo (Source Output). En el nodo principal de la salida, editamos la propiedad "IsSorted", y la ponemos a "true".
  3. Sin salir del diálogo de opciones avanzadas, seleccionamos la columna por la que hemos ordenqado el flujo (DNI) y alteramos la propiedad "SortKeyPosition". En esta propiedad debemos indicar qué posición ocupa la columna en la jerarquía de columnas que ordenan el flujo. En nuestro caso, el flujo está ordenado con respecto a un único criterio, así que la clave de esta columna sería "1".

Siguiendo estos pasos, ya podremos eliminar las transformaciones Sort, con lo que liberaremos una gran cantidad de memoria que bién nos vendrá para ejecutar otras tareas del ETL.

El inconveniente de este método está en que la SORT también nos permite eliminar registros duplicados, cosa que no podemos hacer de con este método que os he descrito. Es una pena que Microsoft no nos haya dado un transformación que elimine duplicados en un flujo de datos ordenado… sin embargo, esto es muy fácil de solucionar con un script. Para eso, tras la Merge podemos poner un script que compruebe la clave del registro actual con la del registro anterior, y desvíe los registros duplicados a la salida de errores (o simplemente añada al flujo un valor booleano, indicando si el registro está duplicado.

¡Felices transformaciones!

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *