En las cocinas de código, suelo dedicar algo de tiempo a la configuración de la base de datos, especialmente a la configuración de compatibilidad. A menudo ciertos ajustes no siguen las mejores prácticas y durante las discusiones con el desarrollador de la aplicación, escucho «oh, nunca cambié estos» o «no estoy seguro del impacto, así que mejor no tocarlos».
Dado que pueden tener un impacto drástico en el rendimiento o el comportamiento de sus aplicaciones, hemos comenzado una serie de publicaciones en el blog para discutir algunos de estos ajustes «secretos«.
Parte 1 de los ajustes de compatibilidad – QUERY BY FORMULA
Estos ajustes obligan a 4D a comportarse como lo hacía en la versión 2004, reduciendo el conjunto de características y el rendimiento. Y es muy fácil de cambiar, pero los clientes tienen miedo de los efectos secundarios desconocidos.
QUERY BY FORMULA era bastante lento en v2004 (porque todos los registros se transferían al cliente), sin mucho valor añadido. En consecuencia, la mayoría de los desarrolladores la ignoraban. Las reglas cambiaron con la v11.
El comando QBF (para ser breve en esta entrada del blog) le permite utilizar cálculos como la búsqueda del tamaño de la imagen o la longitud del texto. Las ventajas de esta función son bastante obvias. Sin embargo, este tipo de cálculos no pueden utilizar un índice, por lo que son más lentos que una consulta indexada.
Pero el comando QBF puede hacer mucho más. Puede combinar grupos de consulta con paréntesis: ((campo1=1) y (campo2=»A»)) O ((campo1=50) y (campo2=»B»)).
No utilizar el comando QBF significa ejecutar dos consultas y utilizar conjuntos, lo que resulta en mucho más tráfico de red, más dependencia del rendimiento de la red y más carga para 4D Server. El optimizador de consultas de 4D Server detecta automáticamente la mejor manera (más rápida) de manejar tales condiciones en los campos de la misma tabla – o incluso en tablas relacionadas.
Y lo mejor de todo es que puede construir relaciones por sí mismo (aka joins), incluso si no se dibuja ningún enlace en modo estructura. Sí, puede construir relaciones dinámicamente para ejecutar consultas (si la opción «QUERY BY FORMULA Uses SQL Joins» está activada).
La opción «QUERY BY FORMULA Uses SQL Joins» puede ser confusa porque no está relacionada con SQL en absoluto, deberías pensar en ella más bien como «QBF soporta relaciones dinámicas».
Usemos una estructura simple como ejemplo:
Tanto QUERY y QUERY BY FORMULA podían utilizarse para buscar mediante una relación, por ejemplo:
QUERY BY FORMULA([Table_2];[Table_1]Field_2="1")
Pero sólo QBF le permite definir explícitamente la relación (permitiendo el uso de cualquier relación posible), en lugar de requerir que una relación definida ya exista. Ahora imaginemos que hay una segunda conexión lógica entre estas dos tablas, pero que no existe ya como relación 4D … Campo3 con Campo2. QBY permite especificar la relación sobre la marcha:
QUERY BY FORMULA([Table_2]; ([Table_1]ID=$var)& \
([Table_1]Field_2=[Table_2]Field_3))
Nota: Cuando se utilizan uniones dinámicas, debe comparar dos campos de tablas diferentes. Si forma parte de una consulta, esto se maneja automáticamente como un join, para definir una relación.
Si quiere buscar un valor en otra tabla, debe asignarlo primero a una variable local. Esto define claramente que se quiere utilizar como constante.
La activación de la opción «QUERY BY FORMULA Uses SQL Joins» es obligatoria para que el «nuevo» editor de consultas(es decir, el editor de consultas introducido con v14) pueda utilizar relaciones. La razón es simple, utiliza el comando QUERY BY FORMULA internamente.
Resumen:
- QUERY BY FORMULA permite utilizar paréntesis para expresar condiciones de consulta complejas, mientras que QUERY sólo permite múltiples condiciones OR o múltiples condiciones AND, pero no una combinación de ambas.
- QUERY BY FORMULA admite las uniones y las consultas dinámicas.
- QUERY BY FORMULA permite utilizar fórmulas, como el tamaño de la imagen.
- QUERY BY FORMULA se ejecuta en el servidor (de forma similar a una consulta normal QUERY), proporcionando la misma o incluso mejor velocidad porque genera menos tráfico de red en comparación con una combinación de QUERY y operaciones de conjunto.
Nota: todo lo anterior es válido para el lenguaje clásico de 4D. El código basado en ORDAse ejecuta siempre en el servidor.
Trabajo de migración requerido para habilitar la compatibilidad
Los ajustes anteriores sólo son visibles en el cuadro de diálogo de compatibilidad para las estructuras creadas con 4D v2004 o anterior. Si no ves estos ajustes, tu estructura es más nueva y siempre se comporta en modo v11, así que estás bien.
Utilice la opción Buscar en el modo de diseño para buscar QUERY BY FORMULA. Como su estructura está en modo «lento» de v2004, la lista debería ser corta. Haga doble clic en cada resultado y compruebe el código.
Siempre que la fórmula utilice constantes, como por ejemplo
QUERY BY FORMULA([Table_2];[Table_1]Field_2="1")
O
QUERY BY FORMULA([Table_2];[Table_1]Field_2=$var)
// similar for var or <>var
Todo está bien, no hay nada que hacer. 4D Remote interpretará la variable y enviará su contenido al servidor (similar a una constante). El valor del cliente se utiliza siempre, incluso si la consulta es ejecutada por el servidor.
Si la fórmula es un método, como por ejemplo
QUERY BY FORMULA([Table_2];RunQuery)
Es necesario abrir y comprobar el contenido del método. Si se pasan parámetros al método, es muy probable que el método sea genérico (pero aún así debe comprobarlo). Si no se pasan parámetros, hay muchas posibilidades de que falle.
Imagine que RunQuery contiene:
$0:= ([Table_2]=myvar)
El contenido de myvar será diferente en 4D Remote y 4D Server, por lo que ejecutar este método en 4D Server fallará. Devolverá resultados diferentes.
Hay dos maneras de solucionar este problema. Para consultas simples como las anteriores, puede simplemente reescribirlo como RunQuery(myvar) y dentro del método usar $1. Problema resuelto.
Pero podrías encontrarte con un método realmente complejo. Miles de líneas de código, sin documentación, escrito hace 20 años. Y sólo se usa una vez al año. Eso es mucho trabajo y riesgo de errores, para un impacto mínimo. Para solucionar el problema, puedes optar por ejecutar este código sólo en modo v2004, manteniendo todo lo demás en modo moderno:
SET DATABASE PARAMETER(Query by formula on server;1)
QUERY BY FORMULA ([Table_2];RunQuery )
SET DATABASE PARAMETER (
Query by formula on server;0)
SET DATABASE PARAMETER permite cambiar el modo sobre la marcha, evitando la necesidad de pasar horas en el código raramente utilizado.
Por último, hay que comprobar si los campos se utilizan de forma que perjudiquen la función de unión. Con v2004 una fórmula como [Table_1]Field_2=[Table_2]Field_3 se interpreta como una búsqueda de contenido estático/fijo, utilizando el contenido del Campo_3. Después de activar la opción «QUERY BY FORMULA Uses SQL Joins», esto se interpreta como una unión.
Por lo tanto, debe comprobar cada QBF para ver si utiliza un nombre de campo en el lado derecho de un operador «=». Si es así, asignarlo a una variable local y utilizar la variable local en la consulta.
Después de haber comprobado todas las apariciones de QUERY BY FORMULAestá listo para activar ambas opciones.
Disfrute de una búsqueda rápida…