Página principal
Artículos y trucos
Catálogo de productos
Ejemplos y descargas
Mis libros
Cursos de formación
Investigación y desarrollo
Libros recomendados
Mis páginas favoritas
Acerca del autor
 
En colaboración con Amazon
 
Intuitive Sight

Problemas con InterBase

En estos días, he "descubierto" o he tenido referencias por artículos en las propias páginas de Borland, de un par de problemas presentes en las actuales versiones de InterBase.

TRANSMISION DE REGISTROS

Como debe saber, InterBase permite definir columnas de tipo varchar de hasta 32.767 caracteres. Como cabe esperar, solamente se almacenan en disco los caracteres realmente utilizados: si la columna NOMBRE pertenece al tipo varchar(30), pero en determinado registro contiene la cadena Pepe, solamente se almacenan esos cuatro caracteres más un contador con la longitud, en vez de desperdiciar 26 bytes adicionales para cumplir con la declaración. Eso es bueno.

Incluso fue motivo de regocijo y cachondeo para los que sosteníamos la superioridad de InterBase respecto a MS SQL Server 6.5 (¡observe bien el número de versión!). En el sistema de Microsoft, sucedía todo lo contrario: se representaban los 30 caracteres, aunque no hiciera falta. Por ahí anda todavía un documento famoso (propagado por Borland) en que se comparan no recuerdo cuál versión de InterBase y SQL Server 6.5; y unos de los argumentos a favor de IB era esta metedura de pata de Microsoft.

Naturalmente, poderoso caballero es Don Dinero. Como este señor es muy amigo de las huestes de Gates, se invirtió a fondo para mejorar aquel SQL 6.5 que solamente se podía utilizar narcotizado o bajo amenaza de tortura. Y ya en SQL Server 7 se eliminó ese inconveniente: los campos de tipo varchar se implementan en la forma más eficiente posible.

... y aquí terminaría mi historia, en un empate técnico, si no hubiera aparecido un artículo técnico en la Borland Community hablando sobre optimizaciones para InterBase. ¡Resulta que, a pesar de la optimización del almacenamiento, cuando InterBase pasa un registro desde el servidor hacia un cliente, se reintroducen todos los bytes sobrantes!

¿Es grave? No, es gravísimo. En primer lugar, porque el ancho de banda de la red es el principal cuello de botella en un sistema cliente/servidor. En segundo lugar, cuando las cosas funcionan como debe ser, es preferible reservar suficiente espacio en los campos varchar para evitar truncamientos. Cuando utilizo SQL Server y tengo que crear un campo para almacenar el nombre de un cliente, no me pongo a sacar cuentas sobre cuáles son los nombres más comunes. Simplemente escojo una cifra suficientemente grande que se encuentre dentro de lo razonable. Pero sin preocuparme del espacio teóricamente "desperdiciado". Y esto me va a obligar a ser más cauto cuando programe con InterBase. Espero que corrijan este problema.

FALLOS DEL OPTIMIZADOR

No es un secreto para nadie los múltiples fallos del "optimizador" de consultas de InterBase. En honor de la verdad, ningún sistema de base de datos es ajeno a ellos. Pero también es cierto que, si no me convence la implementación de una consulta en SQL Server, siempre puedo utilizar varios potentes recursos de este sistema (tablas temporales, por ejemplo) para hacer las cosas a mi modo.

Hace unos meses, durante una consultoría con un cliente de IntSight, descubrimos uno de esos fallos, relacionado con la implementación del operador like. Supongamos que tenemos la siguiente consulta:

select *
from   CLIENTES
where  Nombre like 'In%'

Si existe un índice sobre la columna Nombre, esta consulta puede aprovecharlo para no tener que recorrer todas las filas de la tabla de clientes. Eso es posible porque el comodín '%' se encuentra al final del patrón del operador. En realidad, la consulta anterior es equivalente a la siguiente (suponiendo que la 'o' sigue a la 'n'):

select *
from   CLIENTES
where  Nombre >= 'In' and Nombre < 'Io'

Sin embargo, para evaluar esta otra consulta es inevitable recorrer todos los registros, debido a la presencia del comodín en el prefijo:

select *
from   CLIENTES
where  Nombre like '%sight%'

¿Cómo pensaría usted que se evalúa la siguiente instrucción?

select *
from   CLIENTES
where  Nombre like :patron

La diferencia está en que la consulta ahora utiliza un parámetro. El problema es que el optimizador de InterBase es bastante rígido, y la compilación y optimización tienen lugar antes de la asignación del parámetro. Por lo tanto, como no puede predecirse el valor que va a recibir :patron, se asume lo peor, y se recorren todas las filas de la tabla. Incluso cuando pasamos un patrón razonable como 'In%'.

Moraleja: tenga mucho cuidado con el operador like, especialmente cuando tiene entre manos una consulta con parámetros. Y siempre que pueda, sustitúyalo por el operador starting with, que es una contribución de InterBase:

select *
from   CLIENTES
where  Nombre starting with :patron

Este operador alternativo siempre permite al optimizador aprovechar un índice.

GRAVE ERROR EN INSTRUCCION SELECT

Para terminar, quiero alertar sobre un bug muy peligroso que existe en una de las distribuciones Open Source de InterBase. Este bug no se presenta ni con la versión certificada de InterBase (que viene también con Delphi 6) ni con la última beta (la 2, en este momento) de Firebird.

Está relacionado con el comportamiento de la cláusula into asociada a un select dentro de un procedimiento almacenado. Por ejemplo:

create procedure CodigoCliente(id integer)
    returns (nombre varchar(30)) as
begin
    select Nombre
    from   CLIENTES
    where  IdCliente = :ID
    into   :nombre;
end

Este procedimiento siempre devuelve null en la versión que contiene el error, independientemente de que exista o no un cliente con esa clave. Curiosamente, el error no se produce, al parecer, si el procedimiento tiene más de un parámetro de salida, en su cláusula returns.

No hay que rasgarse las vestiduras, porque hay una versión corregida, pero tenga cuidado y compruebe qué tal funciona su servidor antes de apostar por él. La versión 6.5 de InterBase resuelve el problema de transmisión de registros. Me han comunicado también una solución (más bien, un apaño) para resolver el problema de los select dentro de procedimientos almacenados. Más detalles en el truco Novedades en InterBase 6.5.