Entendiendo a GSTAT (4)

Deja un comentario

Entender como funciona el programa GSTAT es bastante largo. Ya hemos visto algo sobre él en estos artículos:

Entendiendo a GSTAT (1)

Entendiendo a GSTAT (2)

Entendiendo a GSTAT (3)

ahora, continuamos.

Opción -index

Esta es la opción que debemos elegir cuando solamente nos interesan los índices de nuestras tablas.

gstat01

Captura 1. Si haces clic en la imagen la verás más grande

Como es lo usual, la contraseña la extraemos de un archivo de texto y la salida del programa GSTAT la enviamos a otro archivo de texto. Esto último es para facilitarnos la tarea.

gstat02

Captura 2. Si haces clic en la imagen la verás más grande

En la Captura 2. vemos una parte del contenido del archivo de texto que nos muestra información sobre nuestros índices. Los nombres de los índices siempre aparecen ordenados alfabéticamente.

¿Cuál es el significado de lo que estamos viendo?

ASIENTOSCAB es el nombre de la tabla

131 es el identificador que la tabla ASIENTOSCAB tiene dentro de la tabla del sistema RDB$RELATIONS. Es en RDB$RELATIONS donde se  guardan los nombres de todas las tablas de la Base de Datos.

ASC01, ASC02, ASC03, y PK_ASIENTOSCAB son los nombres de los índices

0, 1, 2, 3, los números entre paréntesis que vemos después de los nombres de los índices son los identificadores de los índices menos 1 y nos indican el orden en el cual fueron creados, siendo 0 el primer índice que creamos, 1 el segundo índice que creamos, 2 el tercer índice que creamos y así sucesivamente. Si se creó un índice y luego se lo eliminó, el número que tenía no aparecerá en la lista.

Listado 1.

SELECT
   RDB$INDEX_ID,
   RDB$RELATION_NAME,
   RDB$INDEX_NAME
FROM
   RDB$INDICES
WHERE
   RDB$RELATION_NAME = 'ASIENTOSCAB'
ORDER BY
   RDB$INDEX_ID

gstat03

Captura 3. Si haces clic en la imagen la verás más grande

¿Por qué en la Captura 2. no muestra los verdaderos identificadores sino los identificadores menos 1? Es un verdadero misterio, quizás haya alguna razón valedera para ello pero es dudoso que exista. Probablemente sólo sea por costumbre.

Depth es la cantidad de indirecciones o desviaciones que hay en el árbol B-tree del índice. Lo ideal es que ese número sea como máximo 3. Si es mayor que 3 entonces el índice no será tan eficiente como podría ser ¿cómo lo solucionamos? aumentando el tamaño de la página de nuestra Base de Datos. Si por ejemplo el tamaño de la página es 4096 lo aumentamos a 8192 y volvemos a ejecutar a GSTAT con la opción -index para comprobar si Depth ahora es 1, 2, ó 3 (esos son los mejores valores que puede tener Depth). Si sigue siendo mayor que 3 entonces volvemos a aumentar el tamaño de la página de nuestra Base de Datos y ahora lo ponemos en 16384.

Leaf buckets es la cantidad de páginas que están en el nivel más bajo del árbol B-tree. Es en estas páginas donde se guardan los punteros a las filas de la tabla. En las demás páginas de índice se guardan los enlaces a otras páginas de índice.

Nodes es la cantidad total de filas en la tabla que han sido indexadas. Sin embargo, este número puede ser erróneo porque podrían aparecer filas que han sido borradas con DELETE y aún su basura no ha sido recolectada o también porque las columnas del índice cambiaron de valor. Por eso, es conveniente ejecutar a GSTAT con la opción -index solamente después de un sweep o de un ciclo backup/restore.

Average data length es el tamaño en bytes promedio de los datos de la columna (o columnas) que se indexaron. Como Firebird comprime esos datos antes de grabarlos en una página de índices, el average data length será siempre menor a la suma del tamaño de las columnas de la tabla.

Total dup es la cantidad total de duplicados que tiene un índice. Los índices que se utilizan en las restricciones Primary Key y Unique Key no admiten duplicados, pero los otros índices sí los admiten. Cuantos más duplicados haya, peor es el índice.

 Listado 2.

SELECT
   ASC_ANOEJE,
   ASC_CODSUC,
   ASC_NUMERO,
   COUNT(*)
FROM
   ASIENTOSCAB
GROUP BY
   ASC_ANOEJE,
   ASC_CODSUC,
   ASC_NUMERO

gstat05

Captura 4. Si haces clic en la imagen la verás más grande

gstat04

Captura 5. Si haces clic en la imagen la verás más grande

En la Captura 4. vemos que al ejecutar el Listado 2. se usó el índice ASC01, y en la Captura 5. vemos la cantidad de veces que los valores de ese índice aparecieron. En este caso no hay duplicados, ya que COUNT siempre nos muestra el número 1 pero en otros índices sí podría haber duplicados. El Listado 2. nos ayudará a conocer cuantos duplicados tiene nuestro índice. Recuerda que Total dup puede mostrarte una cantidad incorrecta de duplicados si no has hecho previamente un ciclo backup/restore.

Max dup es la cantidad máxima de valores duplicados que tiene un índice.

Fill distribution es una tabla de frecuencias y seguramente te recordarás de ellas si alguna vez estudiaste Estadísticas. Hay 5 filas, yendo de 20% en 20%, cada fila indicando la cantidad de páginas de índices que están completadas hasta ese porcentaje.

gstat02

Captura 6. Si haces clic en la imagen la verás más grande

En la Captura 6. vemos que hay 8 páginas de índices que están llenas entre un 20% y un 39%. Y hay 3 páginas de índices que están llenas entre un 40% y un 59%. La suma de 8 + 3 es 11, y siempre debe coincidir con leaf buckets.

Esta distribución es mala, estamos usando más páginas que las necesarias. ¿Cómo sabemos eso? porque no hay páginas rellenas entre un 80% y un 99%. En una buena distribución el número mayor debería estar siempre en la última fila, (es decir, en 80% a 99%). ¿Cómo conseguimos eso? Con un ciclo backup/restore y luego usando el backup restaurado.

Artículos relacionados:

Entendiendo a GSTAT (1)

Entendiendo a GSTAT (2)

Entendiendo a GSTAT (3)

El índice del blog Firebird21

El foro del blog Firebird21

Anuncios

Entendiendo las páginas de la Base de Datos

Deja un comentario

El Firebird guarda todos los datos en “páginas”. Nada hay dentro de una Base de Datos que no esté dentro de una página.

¿Qué es una página?

Es una cantidad predefinida y fija de bytes que son tratados como una unidad.

 ¿Cuál es el tamaño en bytes de una página?

Es el tamaño que se definió cuando se creó la Base de Datos. Si no se especificó un tamaño entonces tendrá el valor por defecto que en Firebird 2.5 es de 4096 bytes. Los tamaños posibles son los siguientes:

  • 4096 bytes
  • 8192 bytes
  • 16384 bytes

¿Se puede cambiar el tamaño en bytes de las páginas?

Sí, se puede, para eso se debe usar el programa GBAK. Al restaurar un backup se puede especificar el tamaño que tendrán las páginas de la Base de Datos restaurada. La opción para ello es -page_size [tamaño], por ejemplo: -page_size 8192

Recuerda que el tamaño de las páginas de la Base de Datos original no cambia, el que cambia es el tamaño de las páginas de la Base de Datos restaurada.

¿Y qué ocurre si especifico un tamaño que no sea ninguno de los anteriores?

Entonces el Firebird usará uno de los anteriores. Si el tamaño que especificaste es menor que 4096, usará 4096. Si es mayor que 4096, usará el tamaño predefinido que sea menor al que especificaste. Por ejemplo, si especificaste 16000, usará 8192 porque 8192 es menor que el tamaño que especificaste.

 ¿Y cómo puedo saber el tamaño de las páginas de mi Base de Datos?

Hay dos formas:

1. Usando el programa GSTAT con la opción -h, como vemos a continuación:

PAGES01

Captura 1. Si haces clic en la imagen la verás más grande

El número que verás a continuación de “Page size” siempre será uno de los siguientes: 4096, 8192, 16384

2. Haciendo un SELECT a la tabla MON$DATABASE

SELECT
   MON$PAGE_SIZE
FROM
   MON$DATABASE

NOTA: Versiones antiguas de Firebird también permitían 1024 y 2048, pero ahora esos tamaños ya son obsoletos.

¿Cuántas clases de páginas distintas hay?

Aunque todas las páginas tienen exactamente el mismo tamaño, se las utiliza para distintas cosas. Para saber en que se utiliza cada página tienen un número hexadecimal que las identifica al cual se le llama “tipo de página”.

  • 0x01. Es la Header Page (página de cabecera) y solamente hay una. En ella se guardan datos tales como: el tamaño de las páginas, la versión del ODS, la transacción más antigua, la última transacción activa, la siguiente transacción, etc.
  • 0x02. Es una Page Inventory Page (página de inventario). Puede haber varias. Su sigla es PIP. Siempre la primera PIP está a continuación de la Header Page. Se usa para saber cuales son las páginas que tiene actualmente la Base de Datos y si están libres para ser usadas (o sea, “disponibles”) o no.
  • 0x03. Es una Transaction Inventory Page (página de inventario de las transacciones). Siempre hay al menos una. Aquí se guardan el número de las transacciones y su estado (activa, limbo, confirmada, desechada). El mayor número posible de transacción es 2.147.483.647, cuando una Base de Datos alcanzó a ese número de transacciones se debe hacer un ciclo backup/restore para que el número de la transacción regrese a 1.
  • 0x04. Es una Pointer Page (página de punteros). Hay al menos una por cada tabla (de metadatos o del usuario) que tiene la Base de Datos. En la Pointer Page se guardan los números todas las páginas de datos que pertenecen a una sola tabla. Eso significa que en una página de datos solamente puede haber filas de una sola tabla, nunca se mezclan filas de una tabla con las de otra tabla en una página de datos. Las tablas grandes tienen muchas Pointer Page.
  • 0x05. Es una Data Page (página de datos). Hay al menos una por cada tabla que tiene filas (tanto sean metadatos como del usuario). Todos los datos de esta página corresponden a una sola tabla.
  • 0x06. Es una Index Root Page (página del índice raíz). Cada tabla de la Base de Datos tiene una Index Root Page, la cual describe los índices que tiene esa tabla. Aunque una tabla no tenga índices igual tiene una Index Root Page.
  • 0x07. Es una Index B-Tree Page (página de índice B-Tree). Si una tabla no tiene índices, no tendrá una página de tipo 0x07. Todos los datos de una página Index B-Tree corresponden a un solo índice de una sola tabla.
  • 0x08. Es una BLOB Data Page (página de datos para columnas de tipo BLOB). Solamente existen para tablas que tienen al menos una columna de tipo BLOB. En esta página se guarda el contenido de esas columnas. Todos los datos corresponden a una sola columna de una sola tabla.
  • 0x09. Es una Generator Page (página de generadores). Hay al menos una por cada Base de Datos, aunque ningún generador (también llamado “secuencia”) haya sido definido.
  • 0x0A. Es una Write Ahead Log Page (página de escribir por delante el log). Hay al menos una por cada Base de Datos, pero actualmente no se la está usando, es un desperdicio de espacio, y probablemente ya no exista en Firebird 3.0

¿Qué sucede con una página de datos cuando las filas que guardaba son eliminadas?

Supongamos que en una página se encuentran las filas de la tabla VENTAS y escribes DELETE FROM VENTAS borrando así a todas esas filas. ¿Qué pasa con la página, se la elimina de la Base de Datos? No, permanece ahí, pero en la PIP (Page Inventory Page) se la marca como “disponible”. O sea que puede ser usada nuevamente, y cuando el Firebird necesite una nueva página usará a una de las “disponibles”. ¿Por qué eso? Porque para el Firebird es mucho más rápido usar una página “disponible” (es decir, libre, que nadie la está usando) que alojar una nueva página en el disco duro.

De la misma manera, cuando se hace una “recolección de basura” pueden quedar muchas páginas “disponibles”. Eso es debido a que la “recolección de basura” no elimina a esas páginas de la Base de Datos, sino que las marca como “disponibles”.

Por supuesto que esto implica que si hay muchas páginas “disponibles” hay mucho espacio dentro de la Base de Datos que no está siendo usado para algo útil. Si quieres disminuir el tamaño de la Base de Datos puedes hacer un ciclo backup/restore para que todas esas páginas “disponibles” desaparezcan físicamente.

Resumiendo:

Todo dentro de una Base de Datos de Firebird se guarda dentro de una página, nada está afuera de una página. Todas las páginas tienen el mismo tamaño, aunque se las use para cosas distintas. Ese tamaño se puede especificar al crear la Base de Datos o puede ser cambiado cuando se restaura un backup con el programa GBAK. Se puede usar el programa GSTAT con la opción -h o un SELECT a la tabla MON$DATABASE para conocer el tamaño de las páginas. Cada página dentro de la Base de Datos tiene un número hexadecimal que la identifica y al cual se conoce como el “tipo de página”. Todos los datos dentro de una página corresponden a la misma cosa, nunca se mezclan. Por ejemplo, si una página se usa para guardar las filas de la tabla VENTAS en esa página solamente habrá filas de la tabla VENTAS, jamás habrá en esa página filas de la tabla EMPLEADOS. Cuando todo el contenido de una página de datos es eliminado a esa página se la marca como “disponible” y puede ser reutilizada; si se desea eliminar a todas las páginas “disponibles” hay que hacer un ciclo backup/restore.

Artículos relacionados:

El índice del blog Firebird21

El foro del blog Firebird21

Averiguando el tamaño en bytes de una tabla

Deja un comentario

¿Cuántos bytes ocupa en el disco duro una tabla?

Para responder a esta pregunta podemos hacer uso del programa GSTAT.EXE que viene incluido en la instalación del Firebird y que lo encontrarás en su carpeta \BIN

Hay que ejecutar el programa GSTAT con la opción -t y el nombre de la tabla que nos interesa.

Ejemplo:

Queremos averiguar cuantos bytes ocupa en el disco duro la tabla PROVEEDORES, para ello ejecutamos el programa GSTAT con la opción -t PROVEEDORES:

TAMANO1

Captura 1. Si haces clic en la imagen la verás más grande

Page size nos indica cual es el tamaño de cada página de la Base de Datos, en bytes. Todas las páginas tienen el mismo tamaño. En este ejemplo el tamaño de cada página es 4096 bytes como podemos ver en (1)

Data pages nos indica cuantas páginas ocupa la tabla, en este ejemplo la tabla se llama PROVEEDORES y ocupa 4 páginas, como podemos ver en (2)

Entonces, para saber cuantos bytes está ocupando en el disco la tabla PROVEEDORES simplemente multiplicamos el tamaño de cada página por la cantidad de páginas (4096 * 4) y obtenemos como  resultado 16384 bytes.

Artículo relacionado:

El índice del blog Firebird21

 

Forced writes

1 comentario

En cada una de nuestras bases de datos podemos determinar si los cambios que se realizan en ella se escribirán inmediatamente en el disco duro (FORCED WRITES = ON) o si se escribirán después de un tiempo (FORCED WRITES = OFF)

Si Forced Writes está en ON entonces tenemos dos ventajas:

  1. Los cambios se guardan en forma permanente. Un corte de la energía eléctrica no afectará a los datos ya guardados
  2. Los cambios se guardan siempre en el orden correcto. Por ejemplo, primero se guarda el registro y luego se guarda la entrada del índice que corresponde a ese registro

Si Forced Writes está en OFF tenemos una ventaja:

  1. Los datos se guardan mucho más rápidamente

Entonces ¿cuál es más conveniente?

En general, tener a Forced Writes en ON es lo mejor, esto es aún más notorio en Windows que en Linux. Porque cuando está en ON nos aseguramos que nunca haya pérdida de datos y que la Base de Datos siempre tenga consistencia. Si está en OFF, un corte de la energía eléctrica casi con seguridad hará que la Base de Datos se corrompa. Esa corrupción podría solucionarse, hay programas especializados en esa tarea, pero de todas maneras provocará molestias, inconvenientes y pérdida de tiempo y de dinero.

Podríamos tener Forced Writes en OFF solamente en casos especiales y muy puntuales, por ejemplo para insertar millones de filas desde una tabla externa. Una vez que esa inserción masiva ha finalizado volvemos a colocar Forced Writes en ON.

¿Cómo podemos saber si nuestra Base de Datos tiene Forced Writes en ON o en OFF?

Ejecutando el programa GSTAT.EXE que se encuentra en la carpeta \BIN de donde instalaste el Servidor del Firebird. A ese programa le pones como parámetros el nombre completo o el alias de la Base de Datos que deseas verificar y en la entrada Attributes te mostrará el estado actual de Forced Writes.

FORCED1

Captura 1. Si haces clic en la imagen la verás más grande

Después de escribir GSTAT y el alias de una Base de Datos se puede ver el estado de Forced Writes, que en este caso está en ON. O sea, que es lo correcto durante el uso normal.

¿Cómo se puede cambiar el estado de Forced Writes?

Mediante el programa GFIX.EXE, el cual tiene una opción llamada -write que puede ser sync (para que Forced Writes esté en ON) o async (para que Forced Writes esté en OFF)

FORCED2

 

Captura 2. Si haces clic en la imagen la verás más grande

Como puedes ver, al usar la opción -writes async del programa GFIX.EXE (flecha 1) el estado de Forced Writes se cambió a OFF como nos muestra el programa GSTAT.EXE (flecha 2) porque a continuación de Attributes no hay algo escrito.

Conclusión:

En general, lo conveniente es que Forced Writes esté en ON porque eso nos asegura que todos los datos se guarden y que se guarden en el orden correcto. Un corte de la energía eléctrica no ocasionará pérdidas de datos. Poner a Forced Writes en OFF puede ser muy útil cuando debemos realizar una entrada masiva de datos, pero no debemos olvidarnos de volver a ponerlo en ON apenas esa entrada masiva de datos finalice.

Artículo relacionado:

El índice del blog Firebird21