Las tablas RDB$ y MON$

1 comentario

Dentro de cada Base de Datos de Firebird hay unas tablas especiales, son las llamadas tablas del sistema. Todas ellas empiezan con los caracteres RDB$ o MON$

RDB$ = objetos del sistema

MON$ = tablas de monitoreo

IMPORTANTE: Estas tablas contienen una gran riqueza de información, tú puedes consultarlas y estudiarlas pero no cambies nada de su contenido porque eso conducirá con toda seguridad a una base de datos corrupta.

En ISQL puedes usar el comando SHOW SYSTEM para ver los nombres de todas las tablas del sistema.

Todos los nombres de las columnas de las tablas RDB$ empiezan también con RDB$

Todos los nombres de las columnas de las tablas MON$ empiezan también con MON$

Por ejemplo, la tabla RDB$FILES tiene estas columnas:

RDB$FILE_NAME

RDB$FILE_SEQUENCE

RDB$FILE_START

RDB$FILE_LENGTH

RDB$FILE_FLAGS

RDB$SHADOW_NUMBER

Como ves, el nombre de la tabla empieza con RDB$ y los nombres de todas sus columnas también empiezan con RDB$

 

Anuncios

Insertando una gran cantidad de filas

22 comentarios

A veces podemos tener la necesidad de insertarle miles o millones de filas a una tabla. Hay dos formas de hacer eso:

1. Mediante un ciclo WHILE o similar obtenemos las filas y las insertamos, algo como:

WHILE MiCondición
    Columna1 = Valor de la columna1
    Columna2 = Valor de la columna2
    INSERT INTO MiTabla
        VALUES(Columna1, Columna2)
END WHILE

Esto funciona pero tiene un gran problema: cuando hay muchas filas es lentísimo, exageradamente lento. Van a pasar horas y horas y aún continuará el proceso.

2. Guardando los datos en un archivo de texto y luego usar una sola vez el comando INSERT, de la siguiente manera:

a. Debes generar un archivo .TXT con todas las columnas de tamaño fijo. Eso significa que cada columna siempre debe tener la misma cantidad de caracteres. Por ejemplo, la columna CLI_NOMBRE siempre debe tener 40 caracteres, ni más ni menos.

b. El tamaño de cada columna debe ser exactamente el que se usará en la tabla de Firebird. O sea que si en Firebird la columna CLI_NOMBRE tendrá 40 caracteres en tu archivo de texto .TXT también debe tener 40 caracteres, ni más ni menos.

c. Las filas del archivo .TXT no deben terminar ni con un CHR(10) ni con un CHR(13) ni nada de eso o las columnas quedarán desfasadas.

d. En el Firebird debes crear una TABLA EXTERNA cuya cantidad de columnas y tamaño de cada columna coincida exactamente con las columnas del archivo .TXT

e. Esta tabla externa debe (por supuesto) relacionarse con el archivo .TXT, por ejemplo:

CREATE TABLE
    MiTablaExterna EXTERNAL 'C:\MisDatos\TEMP.TXT' (
        Columna1 Char(12)
        Columna2 Integer);

f. Para insertar las filas del archivo .TXT en la tabla externa del Firebird debes escribir algo como:

INSERT INTO
    TEMP
        (Columna1, Columna2)
    SELECT
        Columna1,
        Columna2
    FROM
        MiTablaExterna

Donde TEMP es una tabla normal del Firebird y MiTablaExterna es la tabla que relacionaste con el archivo .TXT

IMPORTANTE: Lastimosamente si ocurre algún error durante la inserción el Firebird no te dará suficiente información para saber cual es la columna problemática o el error que encontró. Por eso, una buena opción es que todas tus columnas sean de tipo CHAR, ya que eso te permitirá visualizar fácilmente donde está el error. Luego, mediante un CAST conviertes la columna del tipo CHAR al tipo que le corresponde.

OBSERVACIÓN: Un problema que encontré es que si cambias el orden de las columnas en tu tabla de Firebird, éste no se da por enterado, sigue usando el orden antiguo. Un error así puede ser muy insidioso así que debes tomarlo en cuenta.

A pesar de todo eso, la ventaja en velocidad que se obtiene es impresionante. Inserciones que usando el método uno pueden tardar 14 ó 15 horas, usando el método dos no llegan a los 20 minutos, así que sin dudas vale la pena hacer las inserciones con el método 2 cuando la cantidad de filas a insertar es grande.

¿Qué es eso de BLR?

6 comentarios

Las siglas BLR significan Binary Language Representation (Representación en Lenguaje Binario) .

Antes de ser ejecutado todo tu código fuente es traducido a BLR y el que realmente se ejecuta es el código compilado o sea el código en lenguaje binario.

Tu código fuente lo puedes leer y entender fácilmente pero ése no es el que se ejecuta, el que se ejecuta es el representado en lenguaje binario.

¿Por qué?

Porque las computadoras no entienden los códigos fuentes, ellas entienden lenguaje binario. El código fuente es para que los humanos lo escriban y lo lean, porque es fácil de leer y de entender (para quien está en el tema, por supuesto), en cambio el lenguaje binario es una sarta larguísima de ceros y unos que son inentendibles para nosotros.

Por lo tanto, cada INSERT, DELETE, UPDATE, SELECT, etc. que escribes, antes de ser ejecutado es traducido a lenguaje binario.

Esa es una de las ventajas de usar vistas, ya se encuentran en lenguaje binario, no necesitan ser traducidas y por eso la ejecución es muy rápida.

Todos tus stored procedures, triggers y execute blocks el Firebird los guarda de dos formas en las tablas del sistema: como código fuente y como lenguaje binario. El código fuente te servirá cuando necesites hacer alguna modificación, la versión compilada en cambio será la que usará el Firebird cuando lo ejecutes.

Esto tiene una ventaja adicional: puedes borrar todos tus códigos fuente de la Base de Datos y ésta seguirá funcionando exactamente igual que antes, porque el Firebird no usa tu código fuente sino la versión compilada de tu código fuente.

Nota: Ni se te ocurra borrar el código fuente si no tienes un backup de tu Base de Datos o lo perderás para siempre.

 

El uso de SET TERM

1 comentario

Habrás visto que en los stored procedures, en los triggers y en los execute blocks se usa SET TERM (poner terminador) ¿por qué eso?

Cuando grabas un stored procedure, trigger o execute block el Firebird lo analiza para verificar que esté correcto y no tenga errores. Si tiene errores, te muestra un mensaje informándote del error encontrado.

¿Cuándo termina el stored procedure, trigger o execute block? ¿En qué momento el Firebird dice: “hasta aquí debo analizar”?

Cuando encuentra el caracter de terminación. El caracter de terminación es el punto y coma.

Pero…dentro de un stored procedure, trigger o execute block puede haber varias instrucciones, cada una de ellas terminando también con un punto y coma. ¿Y cuál es el problema? que al encontrar al primer punto y coma el analizador terminará su tarea y la instrucción quedará incompleta. Por ejemplo:

    CREATE PROCEDURE MiStoredProcedure
    AS
    BEGIN
        INSERT INTO MiTabla VALUES(123456);
    END;

El analizador finalizará su tarea al encontrar VALUES(123456); y eso es un error porque el BEGIN debe finalizar con un END y nunca se llegó hasta ese END.

¿Cómo se soluciona este problema?

Diciéndole al Firebird que para finalizar el stored procedure, trigger o execute block utilice otro caracter de terminación, no el punto y coma. Al escribir:

    SET TERM ^ ;

Lo que se le está diciendo es: “este stored procedure, trigger o execute block finaliza cuando encuentras el caracter ^”

Desde este momento el caracter de terminacion es el ^ ya no es el ;

Para evitar problemas con otras instrucciones, lo correcto es que vuelvas a poner al punto y coma como caracter de terminación al finalizar tu stored procedure, trigger o execute block.

    SET TERM ^ ;

Por lo tanto el ejemplo te quedará así y estará todo perfecto:

    SET TERM ^ ;
    CREATE PROCEDURE MiStoredProcedure
    AS
    BEGIN
        INSERT INTO MiTabla VALUES(123456);
    END^
    SET TERM ; ^

Un comentario final: como caracter de terminación puedes usar cualquiera que desees, no es obligación usar el ^ aunque sí es el más usado. El único requisito es que el caracter elegido no aparezca dentro de tu stored procedure, trigger o execute block. Por ejemplo, una letra sería una pésima elección porque la probabilidad de que aparezca ahora o en el futuro cuando lo modifiques es muy alta. Recuerda que el analizador finaliza su tarea cuando encuentra el caracter de terminación. Por eso, usar como caracter de terminación una letra (A, B, C, etc.) es lo peor que podrías hacer. Por otro lado, tampoco es obligatorio que se use un solo caracter para terminación, si lo deseas puedes usar varios, por ejemplo:

    SET TERM %&/ ;

es también perfectamente admisible.

¿Cómo saber si alguien más está usando la Base de Datos?

6 comentarios

A veces necesitamos saber si somos los únicos que estamos conectados a una determinada Base de Datos o si alguien más lo está haciendo. Para ello podemos escribir:

SELECT
   *
FROM
   MON$ATTACHMENTS A
WHERE
   A.MON$ATTACHMENT_ID <> CURRENT_CONNECTION

Si vemos alguna fila, no somos los únicos conectados.

Recreando los índices de las tablas

4 comentarios

Los índices son fundamentales para que las consultas a la Base de Datos sean rapidísimas, sin embargo pueden quedar desbalanceados y por ese motivo perdiéndose velocidad.

En estos casos lo que se debe hace es recrearlos. ¿Cómo? muy facilmente:

ALTER INDEX IDX_PERSONAS INACTIVE
ALTER INDEX IDX_PERSONAS ACTIVE

La cláusula INACTIVE cierra el índice y la cláusula ACTIVE lo crea nuevamente.

 

INET/inet_error: read errno = 104

1 comentario

Si encuentras este error, eso significa que hubo un problema en la comunicación entre el Servidor y el Cliente.

 

Older Entries