Usando Servidor y embedded en la misma aplicación

Deja un comentario

Si queremos que nuestras aplicaciones “vuelen”, o sea que se ejecuten a gran velocidad podemos usar la técnica que se explica en este artículo. El autor de este blog usa esa técnica desde hace muchos años con gran suceso.

Entendiendo la situación:

El ancho de banda de todas las redes es limitado, en algunos casos puede ser muy grande pero siempre es limitado. Si demasiados datos transitan por la red ésta se vuelve lenta. En general las aplicaciones de bases de datos no saturan la red salvo que haya demasiados usuarios conectados y demasiadas consultas se estén realizando al mismo tiempo.

Sin embargo, la realidad es que muchas veces la misma red que se usa para las aplicaciones de bases de datos también se usa con otros objetivos, por ejemplo para conectarse a Internet. Y en casos así es frecuente que alguien (aunque no debería hacerlo) esté descargando fotografías, canciones, vídeos o películas.

Ante ese panorama no habrá red que aguante, hagamos lo que hagamos para aumentar la velocidad de nuestras consultas siempre serán lentas porque la red estará saturada.

Entonces, el primer y elemental paso es conseguir que la red se use única y exclusivamente para bases de datos y para nada más, por ningún motivo. Si necesitan una red para Internet, que instalen otra, pero la que se usa para bases de datos debe usarse solamente y exclusivamente para bases de datos. Eso es innegociable.

Pero aún teniendo una red exclusiva algunas tareas de los usuarios pueden ser lentas. Veamos:

Una empresa tiene 5.000 clientes, cuando se va a realizar una venta la aplicación muestra en una grilla los nombres de esos clientes. El usuario elige a unos de ellos.

¿Qué sucedió?

Que la consulta del usuario involucró que por la red transiten los datos de esos 5.000 clientes. Si es un solo usuario quien está vendiendo quizás no sea mucho problema pero ¿y si son 10, 40, 80 o más usuarios?

Allí ya es otro tema, porque ya muchos datos están transitando constantemente por la red.

Entonces, lo que necesitamos es una técnica que nos permita obtener los datos de esos 5.000 clientes pero sin usar la red. ¿Es eso posible?

La solución:

Ya hemos visto que si demasiados datos transitan por una red ésta se vuelve lenta, entonces lo que debemos conseguir es que sean muy pocos los datos que transiten por ella para que cuando lo hagan sea a gran velocidad.

Y eso obtendremos si usamos una Base de Datos auxiliar.

En esta Base de Datos auxiliar guardaremos las tablas de lookup y las tablas maestras. ¿Qué son las tablas de lookup? Las que guardan datos que se insertan una sola vez y luego se usan muchas veces, pero nunca se modifican. Por ejemplo: nombres de localidades, nombres de los tipos de documentos, nombres de los tipos de envases, nombres de las unidades de medida, nombres de las marcas de productos, nombres de sucursales, nombres de las monedas extranjeras, nombres de Bancos, nombres de vendedores, nombres de cobradores, nombres de países, etc. En esas tablas se insertan filas pero nunca se las modifica. Bueno, la excepción sería si se escribió mal el nombre, pero solamente eso, nada más se suele cambiar.

Y en las tablas maestras se guardan los datos de clientes, proveedores, productos, etc.

Tanto las filas de las tablas de lookup como las filas de las tablas maestras se usan principalmente para consultas. Y para asegurarnos que en las otras tablas se ingresen datos existentes. Y eso normalmente se realiza a través de restricciones FOREIGN KEY.

Así, si por ejemplo estamos vendiendo en moneda extranjera estaremos seguros que esa moneda extranjera existe, porque su identificador y su nombre lo extraemos de la tabla de MONEDAS. Y en nuestra tabla de VENTAS nunca tendremos una moneda extranjera inexistente porque una restricción FOREIGN KEY lo impedirá.

Entonces, si queremos que nuestras aplicaciones muestren los datos a gran velocidad lo que debemos hacer es usar una Base de Datos local, no una Base de Datos externa.

La idea es la siguiente:

  • Creamos una Base de Datos auxiliar, que se guardará en el disco duro local y a la cual se conectará mediante embedded
  • En nuestra Base de Datos auxiliar guardamos las tablas de lookup y los datos de consulta de las tablas maestras (típicamente identificador, código, nombre, y a veces algunas columnas más) que se encuentran en el Servidor
  • Cuando un usuario quiere consultar una tabla de lookup o una tabla maestra, verificamos que la cantidad de filas de la tabla auxiliar coincida con la cantidad de filas de la tabla en el Servidor. Si no coincide, a la tabla auxiliar le insertamos las filas faltantes
  • Le mostramos al usuario la tabla auxiliar
  • Cuando el usuario eligió una fila de la tabla auxiliar, consultamos (si hace falta) la tabla remota para obtener los otros datos que necesitamos

Ejemplo:

  • Creamos una Base de Datos llamada AUXILIAR.FDB
  • Siempre nos conectaremos a ella usando embedded
  • A esa Base de Datos le agregamos una tabla llamada CLIENTESAUX con las columnas Identificador, Código, Nombre
  • Cuando el usuario necesita consultar los datos de un cliente, verificamos que el último Identificador de la tabla CLIENTESAUX sea igual al último Identificador de la tabla CLIENTES (que es la tabla que tenemos en el Servidor)
  • Si el Identificador de la tabla CLIENTES es mayor que el Identificador de la tabla CLIENTESAUX, le insertamos a la tabla CLIENTESAUX las filas faltantes
  • Le mostramos al usuario el contenido de la tabla CLIENTESAUX
  • Después que el usuario eligió una fila de CLIENTESAUX extraemos de la tabla CLIENTES que se encuentra en el Servidor los demás datos que necesitamos (su teléfono, su e-mail, etc.)

Ventajas:

  • El usuario consulta una tabla que se encuentra en el disco duro de su computadora, eso siempre es mucho más rápido que consultar una tabla que se encuentra en el disco duro de otra computadora
  • La red se usa al mínimo porque si hay 5.000 clientes transitaron por la red los datos de un solo cliente, no los datos de 5.000 clientes

Desventaja:

  • Se complica la programación de nuestra aplicación porque debemos escribir rutinas que se encarguen de actualizar las tablas auxiliares

Importante:

Con esta técnica se consiguen tiempos de respuesta buenísimos pero hay que tener en cuenta que la aplicación debe conectarse a una sola Base de Datos en el Servidor, ya que si primero se conecta a la Base de Datos “A”, luego a la Base de Datos “B”, luego a la Base de Datos “C”, si hay una sola Base de Datos AUXILIAR.FDB habrá que borrar los datos de cada una de sus tablas cada vez que se cambia de Bases de Datos y luego insertar las filas correspondientes. Allí ya se vuelve ineficiente. La solución en ese caso es tener una Base de Datos auxiliar para cada Base de Datos en el Servidor. O sea AUXILIAR_A.FDB, AUXILIAR_B.FDB, AUXILIAR_C.FDB, etc.

Conclusión:

Si creamos una Base de Datos auxiliar a la cual nos conectamos mediante embedded y guardamos en ella las tablas de lookup y las tablas maestras cuando el usuario haga una consulta obtendrá los datos a gran velocidad porque serán leídos desde su disco duro local lo cual siempre es muchísimo más rápido que leerlos desde un disco duro remoto.

La desventaja es que nuestra programación de la aplicación se complicará porque cada vez que el usuario quiera consultar una tabla de lookup o una tabla maestra deberemos verificar que la tabla auxiliar se encuentre actualizada y si no lo está entonces deberemos actualizarla. Siempre la tabla auxiliar deberá estar actualizada antes de mostrarle los datos que pidió.

Artículos relacionados:

¿Es seguro usar Servidor y embedded al mismo tiempo?

El índice del blog Firebird21

El foro del blog Firebird21

Anuncios

Usando Firebird con WiFi

2 comentarios

En esta época es muy común que haya conexiones WiFi en todas partes, tanto en los hogares como  en las oficinas e inclusive en lugares públicos. Entonces la pregunta es: ¿qué tan eficiente es usar Firebird con WiFi?

Primero, hay que decir que es perfectamente posible pero … pueden ocurrir problemas. Veamos:

Pérdidas de señal

En una red WiFi casi siempre en un momento o en otro ocurren pérdidas de señales, si haces una búsqueda con Google verás que hay millones de personas quejándose de eso. La culpa de la pérdida de señal puede ser del hardware o del software. Pero vayamos a lo nuestro:

El Servidor del Firebird no sabe si te has conectado a la Base de Datos por medio de una red cableada o por medio de WiFi. Eso implica que lo importante es la calidad de tu red, no de si es cableada o WiFi.

Si la culpa de la pérdida de señal es del hardware, entonces hay que reemplazarlo. No pretendas conectar a ochopotocientas computadoras con un router WiFi barato, de esos que cuestan casi lo mismo que una docena de caramelos. Si la conexión será por WiFi entonces el router debe ser de una marca bien conocida, de muy buena calidad. Esto se lo debes aclarar muy bien a tu cliente, y por escrito, para que luego no te echen la culpa de la lentitud o del tiempo perdido. Desde luego que esto se aplica a todo tipo de redes, sean cableadas o WiFi: si tu cliente quiere buena velocidad entonces debe invertir en hardware de buena calidad, no puedes garantizar ni velocidad ni confiabilidad si no es así. Aunque en una red cableada con hardware de mala calidad podrías obtener un resultado aceptable con redes WiFi nunca es así: hardware malo implica rendimientos miserables con bases de datos.

Si la culpa de la pérdida de señal es del software entonces eso significa que no está bien configurado. Y aquí hay varios puntos que tener en cuenta:

  1. El Windows puede desconectarse del router para ahorrar energía. Puedes verificarlo entrando en Panel de Control | Administrador de dispositivos | Adaptadores de red | Nombre_de_tu_router | Propiedades | Administración de energía. Si está marcada la opción “Permitir que el equipo apague este dispositivo para ahorrar energía”, quítale la marca.
  2. En el archivo FIREBIRD.CONF que se encuentra en la carpeta donde instalaste el Firebird hay una entrada llamada DummyPacketInterval que sirve para indicarle al Servidor del Firebird cuantos segundos debe esperar antes de enviarle un paquete vacío de reconocimiento al Cliente. ¿Qué significa esto? Que si el Cliente no está enviando solicitudes al Servidor (un comando INSERT, UPDATE, DELETE, SELECT, etc., por ejemplo) el Servidor no puede saber si el Cliente continúa conectado o si se ha desconectado. La forma de verificar que continúa conectado es enviándole un paquete vacío que solamente sirve para reconocimiento. Si el Cliente le envía una respuesta al Servidor entonces el Servidor sabe que el Cliente continúa conectado. Si el Cliente no le envía una respuesta entonces evidentemente se murió la conexión. La entrada DummyPacketInterval sirve justamente para eso: para decirle al Servidor cada cuantos segundos debe verificar que el Cliente está conectado.
  3. En el punto 1. hemos visto como pedirle al Servidor que verifique la conexión pero … ¿y si queremos que sea el Cliente quien la verifique? Esto siempre es importante, antes de enviarle un comando (INSERT, UPDATE, DELETE, SELECT, EXECUTE PROCEDURE, etc.) al Servidor queremos verificar que hay una conexión activa. La forma más sencilla y rápida de conseguirlo es pidiéndole al Servidor que nos devuelva algún dato, por ejemplo la fecha de hoy. Para ello le podemos enviar un comando como: SELECT CURRENT_DATE FROM RDB$DATABASE y si como resultado obtenemos una fecha entonces estamos seguros de que la conexión está activa (se le dice “viva” en muchos documentos sobre redes). El Cliente solamente necesita saber si la conexión está activa cuando envía una solicitud, para que ésta no rebote; en los demás momentos no le importa.
  4. El Windows puede ayudarnos a mantener la conexión activa. Si se lo pedimos puede enviar paquetes de reconocimiento cada “x” segundos. Los datos en el protocolo TCP/IP viajan en grupos conocidos como paquetes, los cuales están compuestos por una cabecera, los datos del usuario, y la cola. Si en un paquete no se envían datos del usuario entonces puede usarse para saber si una conexión está activa o no. IMPORTANTE: Estas instrucciones son solamente para usuarios avanzados, si no es tu caso ni lo intentes o podrías dejar a tu Windows inservible. No lo olvides: no lo intentes si no sabes muy bien lo que estás haciendo. El Windows viene con un programa llamado REGEDIT el cual nos permite modificar el Registro, también podríamos modificarlo con un archivo que tenga la extensión .REG o con algunos otros programas utilitarios. En el Registro del Windows hay una clave llamada “Parameters” que encontrarás en HKEY_LOCAL_MACHINE | System | CurrentControlSet | Services | Tcpip. A esa clave le puedes agregar los siguientes valores DWORD: KeepAliveInterval, que determina la frecuencia con la cual el Windows repite transmisiones “keepalive” (mantener viva) cuando no recibe respuesta, puedes ponerle 1, lo cual significa que enviará paquetes cada 1 segundo; KeepAliveTime, que determina los segundos que esperará el Windows desde que se terminó la última conexión o intento de reconocimiento para enviar reconocimiento, si por ejemplo le pones 60 eso significa que esperará que hayan transcurrido 60 segundos después de la última conexión o intento de reconocimiento antes de verificar si está activa; TcpMaxDataRetransmissiones, que determina cuantas veces como máximo se enviará un paquete antes de decidir que la conexión está muerta, su valor por defecto es de 5.

Múltiples dispositivos usando la red WiFi

Además del problema que podemos tener con las pérdidas de señal hay otro problema que inclusive puede llegar a ser peor: los usuarios querrán usar la red WiFi para conectar no solamente las computadoras que accederán a las bases de datos sino también tabletas, teléfonos celulares smart, televisores smart, relojes smart, y cualquier otro dispositivo habido o por haber que pueda conectarse a una red WiFi.

Entonces, no podrás evitar que a algún “genio” se le ocurra ver una película on-line mientras otros usuarios necesitan una red rápida. Es muy difícil evitar esas conexiones piratas y siempre tendrán algún muy buen motivo para hacerlas … y lo que conseguirán será que los tiempos de respuesta de las solicitudes a las bases de datos sean paupérrimos.

Conclusión:

 Es posible conectarse a bases de datos de Firebird a través de redes WiFi, pero si se desea un buen tiempo de respuesta el hardware debe ser de buena calidad y el software debe estar bien configurado.

Sin embargo, una buena red cableada siempre será mejor que una buena red WiFi.

Para deslindar responsabilidades siempre es una muy buena idea hacerle firmar un documento a tu cliente que diga algo como: “Para trabajar con bases de datos son preferibles las redes cableadas, las redes WiFi solamente tienen un buen desempeño cuando el hardware es de muy buena calidad y el software está correctamente configurado, en otro caso es una mala opción usarlas. Pero aún con una buena red WiFi siempre la red cableada será más rápida y más confiable. Mi recomendación por lo tanto es usar una red cableada.”

Artículos relacionados:

El índice del blog Firebird21

El foro del blog Firebird21

 

Mejorando el rendimiento de las bases de datos (1)

6 comentarios

Si quieres que las operaciones con tu Base de Datos sean muy rápidas entonces hay 6 aspectos fundamentales que debes considerar:

  1. Hardware
  2. Software
  3. Red
  4. Administración
  5. Diseño de la Base de Datos
  6. Programación

El hardware es todo lo relacionado a la parte física de la computadora donde se encuentra el Servidor del Firebird, la conexión de red y las computadoras clientes. Esto engloba a: cantidad de memoria RAM, cantidad de núcleos, cantidad de discos duros, tipos de discos duros, capacidad de los discos duros, tarjetas de red, router, cablerío, etc.

El software se refiere al Sistema Operativo utilizado, el cual siempre debe ser una versión Server. Por ejemplo: Windows Server, Ubuntu Server, FreeBSD, OS X Server, AIX, HP-UX. ¿Por qué? porque las versiones Server están optimizadas para trabajar como servidores de bases de datos. En cambio las versiones “normales” son para los usuarios que quieren ejecutar sus aplicaciones de Contabilidad, de Control del Stock, navegar por Internet, revisar sus e-mail, visitar su Facebook, jugar sus jueguitos, etc. Estas versiones “normales” también pueden usarse como servidores de bases de datos pero no les pidas velocidad porque no están pensadas para eso.

La red está íntimamente relacionada con el hardware y con la administración. Por un lado, debes instalar tarjetas lo más rápidas posibles, jamás usar tarjetas inalámbricas porque degradan la velocidad, tener un router de buena calidad (olvídate totalmente de esos chinitos que cuestan casi lo mismo que una docena de caramelos), usar el cablerío adecuado, asegurarte que la distancia siempre sea al menos un 20% menor a la especificada (por ejemplo 1000BASE-T tiene un alcance de unos 100 metros, no uses más de 80), y por el otro lado asegurarte que la red se use exclusivamente para comunicarse con las bases de datos y para nada más. Si permites que la red la usen también con Internet y los muchachos se dedican a descargar canciones, vídeos y películas, pues no habrá red que te aguante.

La administración se divide en dos partes: una, la correspondiente al Firebird; otra, la correspondiente a las bases de datos. En la correspondiente a Firebird: ¿qué arquitectura estás usando: SuperServer, Classic, SuperClassic? ¿Cuántos núcleos están configurados? ¿en cuál disco guardas los archivos temporales? ¿en cuál disco haces el shadow?. En la correspondiente a la Base de Datos: ¿cuál es el tamaño del caché? ¿cuál es el tamaño de la página? ¿qué valor tienen la OAT y la NT? ¿cuáles son las estadísticas de los índices? ¿cuántos usuarios concurrentes tienes como máximo? ¿el sweep es manual o automático? ¿cada cuánto tiempo se hace un backup con GBAK? ¿hay transacciones que demoran mucho tiempo, cuál es el programa culpable?, etc.

El diseño de la Base de Datos es fundamental para conseguir buenos rendimientos. Aquí deberías preguntarte: ¿están todas las tablas normalizadas? ¿todas las tablas tienen las restricciones que deberían tener? ¿faltan índices para hacer las consultas más rápidas? ¿sobran índices, pues hay algunos que casi nunca se usan? ¿se pueden cambiar las estructuras de algunas tablas para conseguir mayores velocidades en las operaciones? ¿faltaría algún trigger?, etc.

En relación a la programación debes preguntarte: ¿todas las transacciones finalizan con un COMMIT o con un ROLLBACK? ¿están todas las consultas optimizadas?  ¿Hay momentos en los cuáles se realizan inserciones masivas de datos? ¿se pueden hacer transacciones más cortas?, ¿se puede reemplazar un stored procedure por otro más rápido?, ¿se puede reemplazar una vista por otra más rápida (quizás usando tablas temporales, tablas CTE, etc.)?, ¿se puede mejorar la velocidad de las inserciones masivas de datos?, etc.

Conclusión:

Como puedes ver, conseguir un rendimiento óptimo de las bases de datos no es sencillo porque involucra a muchos aspectos diferentes. Si mejoras cualquiera de ellos entonces verás un aumento en las velocidades pero para llegar al máximo debes mejorarlos a todos. Claro, eso tomará tiempo y dinero así que debes evaluar si vale la pena hacer el trabajo de optimización.

Artículos relacionados:

¿Cuál Sistema Operativo usar en el Servidor?

Consejos para optimizar el rendimiento de las bases de datos

Consultas lentas, causas y soluciones

El índice del blog Firebird21

La doble validación

1 comentario

Como seguramente sabes, debes evitar que entre basura en tu Base de Datos. ¿Y qué es basura? cualquier dato que está pero que no debería estar. Por ejemplo, el identificador de un producto que no existe o un precio de venta negativo cuando todos los precios sabemos que deben ser positivos (o en todo caso cero, pero nunca negativos).

Todas las validaciones que involucren a filas o columnas de una tabla pueden y DEBEN ser realizadas dentro de la Base de Datos en sus triggers o stored procedures.

Sin embargo, hay también validaciones que pueden y DEBEN ser realizadas afuera de la Base de Datos.

¿Cuáles son esas validaciones?

Todas aquellas que no requieran conocer el valor de una columna para saber si el dato que se quiere insertar o actualizar es correcto o incorrecto.

Por ejemplo, si sabemos que todos los precios de venta de nuestros productos deben ser positivos sí o sí, entonces a esa validación la hacemos en el código fuente del lenguaje de programación que estamos usando (Visual FoxPro, Visual Basic, C, C++, Delphi, Java, PHP, etc.)

Y por supuesto, volvemos a validar que el precio sea positivo dentro de nuestra Base de Datos, normalmente en un trigger o a veces en un stored procedure.

A esto se le llama doble validación.

¿Y por qué haríamos una doble validación?

Porque si la validación no la hacemos en nuestra aplicación y la hacemos solamente en nuestra Base de Datos puede ocurrir que encontremos un error y eso implicaría un tráfico innecesario en la red. Por ejemplo:

  • Desde nuestra aplicación queremos insertar una nueva fila a la tabla de PRODUCTOS
  • Entre los datos que pedimos que tenga la nueva fila está el precio de venta, el cual es negativo
  • Un trigger de la tabla de PRODUCTOS detecta que el precio de venta es negativo y devuelve una excepción
  • El Servidor le avisa al Cliente y éste a nuestra aplicación que ocurrió un error en el precio de venta

¿Y cuál es el problema de hacerlo así?

Que por la red estuvieron viajando el precio de venta negativo (para que la Base de Datos pudiera recibirlo) y luego la excepción con su correspondiente mensaje de error.

Y no eran necesarios esos viajes porque la validación de que el precio de venta no sea negativo pudo haberla realizado la aplicación antes de enviarlo por la red.

Si tu Base de Datos es usada por pocos usuarios y tu red tiene un buen ancho de banda entonces no se detectará una demora pero …. está mal, el concepto está errado, en todo momento debes preocuparte por conseguir que por la red viajen la menor cantidad posible de datos. Cuanto menos se use la red, mucho mejor. Y si tu Base de Datos está en Internet entonces lo anterior es muchísimo más importante porque Internet es una red lenta, mucho más lenta que tu red local.

Resumiendo, en todos aquellos casos en los cuales no es necesario conocer el valor de una columna para poder validar el dato la validación la deben realizar la aplicación y luego la Base de Datos también.

Por ejemplo: que el nombre no esté vacío, que la fecha no sea NULL, que el precio de venta no sea negativo, que el importe cobrado sea mayor que cero, etc. Todos estos datos y muchos más los puede validar la aplicación, no necesita enviarlos a la Base de Datos para descubrir que dichos datos no son aceptables.

Si tu aplicación funciona bien cuando hay pocos usuarios pero funciona desastrosamente cuando hay miles de usuarios algo hiciste muy mal. Y no deberías esperar a tener miles de usuarios para empezar a optimizar el tráfico en la red, mañana mismo o la semana que viene podrían proponerte que vendas una aplicación que usarán miles de personas a la vez y estarías desperdiciando un tiempo valioso en optimizar el tráfico en la red cuando desde el principio mismo podrías haberlo hecho correctamente.

Recuerda: por la red solamente deben viajar los datos que son imprescindibles, y cuantas menos veces viajen, mucho mejor.

.