lunes, 30 de mayo de 2016

Realizar consultas eficientes

Hoy vamos a explicar un poco un tema que suele pasar desapercibido pero que cobra gran importancia cuando queremos poner en valor la información que tiene nuestro sistema. Vamos a verlo con un ejemplo, que siempre es más sencillo.
Cortesía de Pixabay.com

Supongamos que nuestro sistema almacena información sobre facturas. Algunos datos típicos pueden ser:
  • Referencia.
  • Fecha.
  • Emisor.
  • Receptor.
  • Concepto.
  • Importe.
  • Descuento.
  • Total.
Podríamos tener los siguientes valores de metadatos para unos cuantos documentos.

Referencia
Fecha
Emisor
Receptor
Concepto
Importe Descuento Total
12723 12/07/2007 Teleco Manuel Sánchez Servicios de ADSL y telefonía 37,86 12,34 25,52
22538 21/09/2010 Teleco Juan Márquez Servicios de ADSL y telefonía 52,12 20,00 32,12
49347 17/01/2012 Teleco María Santos Servicios de ADSL y telefonía 24,12 5,20 18,92
78122 02/12/2013 Teleco Luisa Estévez Servicios de ADSL y telefonía 42,12 9,11 33,01

Consultar el sistema, ¿para qué?

Imaginemos que la dirección de la empresa Teleco, decide fidelizar a aquellos clientes que tengan un descuento superior a 10 EUR. Para ellos, necesitamos conocer saber cuáles facturas tienen en su campo "descuento" un valor superior al indicado. Esto se consigue con una consulta.

Vale, y ¿cómo lo hago?

Cualquier sistema de información dispone de una forma de consulta (todo el mundo conoce la elegida por Google). Este sistema puede ser más o menos sofisticado y permitir consultas más o menos complejas. Athento ofrece un sistema bastante intuitivo, flexible y muy potente para realizar estas consultas. Por ejemplo, para obtener la información que buscábamos en el punto anterior, bastaría escribir algo como esto en la consulta al sistema:

SELECT * FROM Invoice WHERE invoice:discount > 10

Esto nos devolverá todas las facturas cuyo descuento sea superior a 10 EUR. Pero no es suficiente, entre los resultados el sistema nos devolverá también aquellas facturas que hayan sido borradas (traducido al lenguaje de consulta, esto es ecm:currentLifeCycleState = 'deleted').

Por tanto, ya tenemos que añadir alguna cláusula más a la consulta para obtener los datos que realmente queremos. Si además, queremos introducir condiciones presentes en otros esquemas de datos, debemos añadir más información a la consulta.

Por ejemplo, es fácil imaginar que las facturas además de la información vista anteriormente, almacenen datos de contacto del cliente como dirección postal, teléfono de contacto o dirección de correo electrónico. Si quisiéramos incluir en la consulta únicamente aquellas facturas que dispongan de correo electrónico informado para poder hacer una campaña de mailing, la consulta quedaría así:

SELECT * FROM Invoice WHERE invoice:discount > 10 AND ecm:currentLifeCycleState != 'deleted' AND customer:email != null

Luego veremos qué problemas puede tener esta consulta.

Eficiencia en la consulta, motivos para darle importancia

En este ejemplo estamos lanzando la consulta de forma manual, pero esto no se aproxima mucho a un caso real. Lo habitual, es que sean procesos automáticos los que lancen las consultas y procesen los resultados haciendo algo útil con ellos (el envío de correo, envío de SMS, inclusión en informes, etc.).

Cuando el sistema lance esta consulta varias veces por minuto, a la vez que lanza otras tantas de otros procedimientos automáticos, el sistema se volverá lento si no le ayudamos a buscar los datos de forma eficiente. Si además, las consultas obtienen como resultado un número elevado de registros, seguro que estamos perjudicando innecesariamente el rendimiento.

Y el tiempo es dinero y nadie quiere un sistema lento, ¿verdad?

Cómo hacer una consulta eficiente

Una consulta en Athento ECM tiene el siguiente formato:

SELECT [metadatos a visualizar]
FROM [tipo documental]
WHERE [[condición de selección] AND|OR [condición de selección] AND|OR [condición de selección]...]
[ ORDER BY [[metadato], [metadato],...]

Podemos establecer unas normas básicas para hacer una consulta:
  1. Obtener exactamente los resultados que necesitamos. Si nos interesan 145 resultados, la consulta debe obtener exactamente esos 145 resultados. Volviendo al caso del mailing, si en el resultado incluimos algún registro sin dirección de correo electrónico, no fallará nada (el email no será enviado), pero estaremos desperdiciando el rendimiento del sistema en algo inútil. Por tanto, como norma general, hay que ajustar las cláusulas de la consulta todo lo posible.

    Algunas cláusulas relevantes para los documentos de Athento, son las siguientes:
    ecm:mixinType != 'HiddenInNavigation' 
    AND ecm:isVersion = 0 
    AND ecm:isProxy = 0 
    AND ecm:currentLifeCycleState != 'deleted'

    El esquema ecm contiene información relevante sobre el estado del documento como si se trata de una versión o si es un documento oculto o "enlace" (proxy) a otro documento. La cláusula del ciclo de vida también puede ser muy importante para hacer una consulta cuando los documentos siguen un ciclo de vida (aprobado, validado, revisado, publicado, etc.).

  2.  Utilizar las condiciones más restrictivas al comienzo. Esto facilitará al sistema la planificación de la consulta. Aunque ya cuenta con planificadores que eligen la mejor estrategia, nunca está de más hacerlo coherente. Además, facilitará su comprensión. Por ejemplo, si el dato más restrictivo es el email (porque hay pocos clientes con valor en el campo email), podríamos filtrar primero por este campo.
    SELECT * FROM Invoice WHERE ecm:mixinType != 'HiddenInNavigation' AND ecm:isVersion = 0 AND ecm:isProxy = 0 AND customer:email != null AND invoice:discount > 10 AND ecm:currentLifeCycleState != 'deleted'
  3. Involucrar el menor número de esquemas posible. Cada esquema es almacenado en una tabla de la base de datos y juntarlas es caro en términos de rendimiento. Si hacemos al sistema saltar de una a otra, será más costoso y tardará más. Por ejemplo, si disponemos de alguna información similar en un metadato de un esquema que ya estemos utilizando, es preferible no cambiar de esquema. Supongamos que el email está informado también en el esquema invoice, cambiaríamos la consulta como sigue:

    SELECT * FROM Invoice WHERE ecm:mixinType != 'HiddenInNavigation' AND ecm:isVersion = 0 AND ecm:isProxy = 0 AND invoice:email != null AND invoice:discount > 10 AND ecm:currentLifeCycleState != 'deleted'

    De este modo, no es necesario acceder a los datos del cliente, sino únicamente a los de la factura.
  4. No ordenar los datos si no es estrictamente necesario. Por ejemplo, en una consulta para obtener informes sí que nos interesará mantener algún orden, ya que lo va a leer una persona y encontrará más fácilmente los datos si los ordenamos por antigüedad o por orden alfabético. 

    SELECT * FROM Invoice WHERE ecm:mixinType != 'HiddenInNavigation' AND ecm:isVersion = 0 AND ecm:isProxy = 0 AND invoice:email != null AND invoice:discount > 10 AND ecm:currentLifeCycleState != 'deleted' ORDER BY invoice:date DESC

    Si en el resultado no es importante el orden, mejor excluímos la cláusula ORDER BY.
  5. Usar condiciones incluyentes. En una cláusula numérica, esto puede ser más relevante de lo que parece. En nuestro ejemplo, el sistema buscará para todos los documentos, el valor de invoice:discount y comprobará que supere el valor 10. Sin embargo, si sabemos que no hay descuentos entre los 9 y 10 EUR, podemos hacer algo así:

    SELECT * FROM Invoice WHERE ecm:mixinType != 'HiddenInNavigation' AND ecm:isVersion = 0 AND ecm:isProxy = 0 AND invoice:email != null AND invoice:discount >= 9 AND ecm:currentLifeCycleState != 'deleted' 

    Esta consulta le permite al sistema ordenar los resultados por el campo discount y escoger todos los que queden por encima del 9 (que son los de 10 o más EUR de descuento), mejorando el rendimiento de la consulta.
  6. Evitar el uso de comodines. Es una práctica habitual cuando uno quiere encontrar rápidamente un registro el uso de comodines. En Athento es posible hacer estas consultas con el carácter '%' y el operador LIKE o ILIKE. Por ejemplo, si queremos únicamente los apellidos que comiencen por A para la campaña de mailing, podríamos hacer esto:

    SELECT * FROM Invoice WHERE ecm:mixinType != 'HiddenInNavigation' AND ecm:isVersion = 0 AND ecm:isProxy = 0 AND invoice:email != null AND invoice:discount >= 9 AND ecm:currentLifeCycleState != 'deleted' AND customer:surname1 LIKE 'A%'

    Esto nos filtrará el resultado dejando únicamente aquellos registros cuyo campo primer apellido comience por A. Sin embargo, es una consulta muy costosa en términos de rendimiento y hay que tratar de evitarla. 

    Una posible solución, es incluir un nuevo campo que nos ayude a encajar al cliente en un "grupo de mailing". Como además, ya sabemos que hay que evitar los cambios de esquema, podríamos denominar a este campo invoice:mailinggroup y darle un valor inicial al cargar la factura por primera vez en el sistema en función de su primer apellido.  De este modo, transformaríamos la consulta en:

    SELECT * FROM Invoice WHERE ecm:mixinType != 'HiddenInNavigation' AND ecm:isVersion = 0 AND ecm:isProxy = 0 AND invoice:email != null AND invoice:discount >= 9 AND ecm:currentLifeCycleState != 'deleted' AND invoice:mailinggroup = 'A'

    Que resulta mucho más eficiente en términos de rendimiento.
  7. Evitar el uso de negaciones. Es mucho más rápido para el sistema determinar una coincidencia que afirmar que no existe coincidencia. Suponiendo que quisiéramos obtener las facturas cuyo importe NO supere los 30 EUR, es mejor decirle al sistema:
    invoice:total <= 30
    que
    NOT (invoice:total > 30)


    El operador NOT introduce una nueva operación sobre cada resultado. Si existe complementario, hay que hacer lo posible por usarlo. Y si no existe, lo posible por crearlo ;-).
     
  8. Tipos de datos. El tipo de valores que puede almacenar un campo es también importante a la hora de tener en cuenta el rendimiento. Por ejemplo, al sistema le cuesta menos manejar números que letras o palabras. Es más rápido decidir que 1 es menor que 2 que decidir que "África" va antes que "Europa". Por ello, a la hora de diseñar el sistema, hay que tener en cuenta estos tipos y usar siempre que sea posible campos numéricos o letras antes que palabras o textos largos (como una descripción) en las consultas. Para ilustrarlo, establecer un filtro por el campo concepto, no tiene mucho sentido y seguramente nos exigiría el uso de comodines desaconsejado como ya hemos visto:
  9. SELECT * FROM Invoice WHERE ecm:mixinType != 'HiddenInNavigation' AND ecm:isVersion = 0 AND ecm:isProxy = 0 AND invoice:email != null AND invoice:discount >= 9 AND ecm:currentLifeCycleState != 'deleted' AND invoice:mailinggroup = 'A' AND invoice:concept = 'Servicios de ADSL y telefonía'

    Obligar al sistema a filtrar por este campo hará la consulta más ineficiente puesto que tiene que revisar cada letra de cada palabra de la frase 'Servicios de ADSL y telefonía". Por tanto, en la medida de lo posible, utilizar numéricos o letras.



  10.  Limitar el número de resultados. Es habitual que nuestras consultas obtengan un número elevado de resultados. Si el sistema dispone de algunos millones de documentos, casi con toda seguridad, cualquier consulta con sentido, obtenga unos cientos de miles. Es por ello que, conviene dividir el resultado en bloques que permitan una mejor gestión. Por decirlo en términos sencillos, "mejor pedir 100 veces 1000 resultados que pedir 1 vez 100.000 resultados". Para preparar una respuesta tan grande, el sistema necesitará muchos recursos (CPU, memoria y sobre todo, tiempo).
  11. Las consultas en Athento se pueden hacer de 2 formas:
    - Navegando en el sistema, en cuyo caso ya disponemos por defecto de la opción de decidir el tamaño de página.
    - Vía API, en cuyo caso es conveniente añadir los siguientes 2 parámetros a la consulta:

    /site/api/v1/query?pageSize=1000&currentPageIndex=1&query=SELECT ...

    De este modo, podemos pedirle al sistema las páginas de 1 en 1 cambiando el parámetro currentPageIndex.

  12. Revisar, revisar y revisar. Y probar las consultas muchas veces con diferentes variantes comparando resultados que permitan establecer cuál es la mejor estrategia para cada caso. Los puntos anteriores son sólo orientativos, es posible que en algún caso concreto saltarse alguno de estos consejos pueda ser beneficioso.
También te puede interesar conocer Cómo Athento ECM aplica la tecnología Elastic Search, una de las principales tecnologías en cuanto a motores de búsqueda, para mejorar el rendimiento de la plataforma y la experiencia de los usuarios cuando necesitan acceder a información. 


Caso de Uso: Clasificación Automática de Documentos Legales

No hay comentarios:

Publicar un comentario en la entrada

AddThis