Entendiendo a GSTAT (3)

Deja un comentario

Ya hemos visto algunas de las características del programa GSTAT en estos artículos:

Entendiendo a GSTAT (1)

Entendiendo a GSTAT (2)

ahora continuaremos analizándolo.

Opción -data

Esta es la opción que debemos elegir cuando solamente nos interesan las páginas de datos. Como recordarás, en Firebird todo se guarda dentro de páginas. En cada página se guarda solamente una clase de ítems, nunca jamás se mezclan. Así por ejemplo tenemos una página de cabecera, una o varias páginas para las transacciones, una o varias páginas para los datos, una o varias páginas para los índices, etc.

La opción -data nos informa sobre los datos que se encuentran dentro de nuestras tablas. Por ejemplo, si tenemos una tabla llamada ALUMNOS los nombres de los alumnos se encontrarán dentro de una o varias páginas de datos. Si tenemos una tabla llamada PROFESORES los nombres de los profesores se encontrarán dentro de una o varias páginas de datos. Pero las páginas donde se encuentran los nombres de los alumnos son distintas a las páginas donde se encuentran los nombres de los profesores. Es decir, en una página de datos podríamos tener nombres de alumnos, o nombres de profesores, pero jamás de ambos.

Eso significa que una tabla puede tener muchas páginas de datos, y que todas esas páginas le corresponden exclusivamente a esa tabla. Por ejemplo, los nombres de los ALUMNOS podrían encontrarse en las páginas 12.345, 12.346, 20.118, 20.129, y los nombres de los PROFESORES podrían encontrarse en las páginas 11.521 y 12.379, los números son siempre distintos.

gstat01

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

En la Captura 1. invocamos a GSTAT con la opción -data para que nos muestre información sobre los datos contenidos en nuestras tablas y, como es lo normal, enviamos esa información a un archivo de texto para poder analizarlo con más facilidad.

Abrimos ese archivo de texto con el Bloc de Notas del Windows y vemos lo siguiente (Nota: los nombres de nuestras tablas siempre aparecen ordenados alfabéticamente):

gstat02

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

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

ASIENTOSCAB es el nombre de nuestra tabla

(131) es el identificador de esta tabla en RDB$RELATIONS, lo cual podemos comprobar facilmente así:

gstat03

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

Como podemos ver en la Captura 3., el identificador 131 le corresponde a la tabla ASIENTOSCAB. En RDB$RELATIONS se guardan los nombres de todas las tablas que tiene la Base de Datos.

Primary pointer page es número de la primera página donde se guardan los punteros a las páginas de datos. ¿Qué significa eso? Bien, como ya sabemos, cada tabla puede tener varias páginas de datos y los números de esas páginas deben guardarse en algún lado. El lugar donde se guardan es en una Pointer Page. O sea que en una Pointer Page se encuentran los números de cada una de las páginas de datos de una tabla. El número 502 que vemos en la Captura 2. significa que en la página 502 se encuentran los números de las páginas de datos de la tabla ASIENTOSCAB. Las tablas grandes pueden necesitar de varias Pointer Page, la Primary pointer page es la primera de esas páginas. Por ejemplo, en la página 502 (que como ya sabemos es una pointer page) podríamos tener los números 31.218, 31.219, 92.128; eso significa que en las páginas cuyos números son 31.218, 31.219, y 92.128 se encuentran datos de la tabla ASIENTOSCAB.

Index root page es el número de la primera página donde se guardan los punteros a los índices. Así como tenemos páginas donde se guardan los datos de una tabla también tenemos páginas donde se guardan los índices de esa tabla. El número 503 que vemos en la Captura 2. significa que en la página número 503 se encuentran los punteros a las páginas de índices de la tabla ASIENTOSCAB. En otras palabras, los números que se encuentren en la página 503 serán los números de las páginas donde se encuentran los índices de la tabla ASIENTOSCAB. Si por ejemplo en la página 503 están los números 14.127 y 29.218 significa que en esas páginas hay índices que corresponden a la tabla ASIENTOSCAB.

Data pages es la cantidad total de páginas de datos de nuestra tabla. En la Captura 2. vemos que la tabla ASIENTOSCAB está usando 148 páginas de la Base de Datos. Hay que tener en cuenta algo importante aquí: algunas de esas páginas pueden contener basura dejada por los comandos UPDATE y DELETE, o tener datos de transacciones que aún no han finalizado con un COMMIT. O sea que no necesariamente todas las 148 páginas que usa ASIENTOSCAB contienen datos útiles.

Data page slots es la cantidad de punteros que hay en las pointer pages y frecuentemente es igual que data pages ¿por qué eso? porque cada página de datos tiene un puntero que guarda ese número de página. Si observamos la Captura 2. veremos que data pages es 148 y que data page slots también es 148. Eso es lo normal, y está muy bien que así sea, significa que la tabla ASIENTOSCAB usa 148 páginas de datos y que hay 148 punteros indicando cuales son esos números de página. Si los números son diferentes, eso no es un error. ¿qué significa que los números sean diferentes? Cada vez que el motor del Firebird necesita una nueva página para guardar los datos de una tabla guarda el número de esa página en una pointer page de esa tabla. Si más adelante esa página que tenía datos ya no los tiene porque un comando DELETE los borró, el puntero que guardaba  ese número de página permanece en la pointer page, no es borrado de allí. ¿Por qué no es borrado? porque si más adelante la tabla necesita una nueva página de datos usará (de ser posible) una página de datos que ya había usado anteriormente. La finalidad de hacerlo así es que eso acelera el proceso. O sea, es mejor reusar una página de datos vacía que crear una nueva página de datos.

gstat04

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

En la Captura 4. vemos que la página número 502 es una pointer page, que corresponde a la tabla ASIENTOSCAB y que contiene los números de las páginas de datos que tienen datos de la tabla ASIENTOSCAB. O sea que la página número 31.218 es una página de datos y los datos allí contenidos corresponden a la tabla ASIENTOSCAB. Lo mismo se aplica a los demás números que vemos en la segunda columna.

gstat05

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

En la Captura 5. vemos las estadísticas de la tabla CUENTAS y observamos que data pages es distinto que data page slots. ¿Qué significa eso? que alguna vez la tabla CUENTAS tuvo 85 páginas de datos pero ahora solamente está usando 15 de esas páginas, las restantes 70 están vacías, sin datos, pero disponibles para ser re-utilizadas cuando la tabla CUENTAS las necesite. Esas páginas que ahora están vacías alguna vez contuvieron datos pero esos datos fueron borrados con un comando DELETE o cuando se recolectó la basura. Si una página solamente contenía basura la recolección automática de basura o un sweep podrían eliminar a esa basura pero no liberan a la página, esa página sigue perteneciendo a la misma tabla. Cuando un comando INSERT o un comando UPDATE o un comando DELETE necesite de una nueva página de datos para escribir lo que necesita escribir, se usará una de esas páginas de datos que ahora están vacías.

gstat06

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

En la Captura 6. vemos que la tabla CUENTAS tiene una pointer page cuyo número es 498 y que nos indica cuales de sus páginas de datos contienen datos y cuales están vacías. Esas páginas de datos que ahora están vacías se usarán alguna vez si la tabla CUENTAS necesita más páginas de datos. ¿Y cuándo la tabla CUENTAS podría necesitar más páginas de datos? Cuando las páginas que está usando ahora se llenen. Una página podría llenarse porque el comando INSERT ha agregado nuevas filas o porque los comandos UPDATE o DELETE han agregado versiones viejas de una fila. En general, el comando INSERT llena una página hasta un 80% de su capacidad y deja un 20% libre para que los comandos UPDATE y DELETE coloquen allí las versiones antiguas de las filas. ¿Por qué hace eso? Para acelerar el proceso, porque es más rápido guardar las versiones viejas de una fila en la misma página de datos que contiene a esa fila que usar una nueva página de datos. Por ejemplo, si la fila cuyo identificador es 12.345 se encuentra en la página número 32.334 y se hace un UPDATE o un DELETE a la fila con identificador 12.345 lo más conveniente es que las versiones viejas de esa fila también se guarden en la página número 32.334, eso es más rápido que guardar las versiones viejas en otra página de datos.

Mirando los números de data page slots y de data pages podemos saber cuantas páginas de nuestra tabla contienen solamente basura y por lo tanto están disponibles para ser utilizadas. Según la Captura 5. vemos que data page slots es 85 y que data pages es 15, eso implica que hay 70 páginas de datos vacías y disponibles.

Un ciclo backup/restore hace que ambos números sean iguales. En el backup restaurado la cantidad de data pages será siempre igual a la cantidad de data page slots.

Average fills es el promedio de llenado de las páginas de datos, e incluye a las versiones viejas de las filas (las versiones viejas son creadas por los comandos UPDATE y DELETE). Mirando la fill distribution tendremos más detalles.

Fill distribution es una tabla de frecuencias. Si alguna vez estudiaste Estadísticas seguramente las recordarás.

gstat02

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

Esta tabla de frecuencias tiene 5 filas, que van de 20% en 20% y sirve para indicarnos como están llenadas las páginas de datos.

Mirando la Captura 7. descubrimos que hay 97 páginas de datos que están llenas entre un 0% y un 19%, o sea que en esas 97 páginas de datos hay muchísimo espacio libre.

Hay 5 páginas de datos que están llenas entre un 20% y un 39%

Hay 20 páginas de datos que están llenas entre un 40% y un 59%

Hay 3 páginas de datos que están llenas entre un 60% y un 79%

Hay 23 páginas de datos que están llenas entre un 80%  y un 99%, o sea que hay muy poco espacio libre en ellas

La suma de esas cantidades de páginas siempre debe ser igual a data pages. Veamos si es así: 97 + 5 + 20 + 3 + 23 = 148. Está perfecto, así debe ser.

Artículos relacionados:

Entendiendo a GSTAT (1)

Entendiendo a GSTAT (2)

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