Anuncios

Bienvenidos sean a este post, hoy hablaremos sobre los caches de MyISAM.

Anuncios
Anuncios

Los indices de este motor son almacenados en una estructura de datos llamada cache de claves o buffer de claves (menos frecuentemente), este cache esta pensado para reducir mayoritariamente el acceso fisico a los archivos de los indices, inclusive todos estos indices pueden ser modificados en memoria y solo despues se bajaran los cambios al disco, cache puede ser desactivado pero dentro de mariadb no tenemos un cache especial para los datos y por lo tanto se usaran los mecanismos de cache propios del sistema, si manejamos muchas tablas de este tipo de motor el tamaño del cache deberia ser el mas grande posible por lo contrario si no es el motor principal de las tablas se puede dejar en el tamaño minimo disponible, la variable que determina este tamaño es key_buffer_size, por ultimo este cache no se puede desactivar completamente dado que si no usamos a Aria para las tablas temporales se procede a usar a MyIsam y en este caso este cache deberia estar activado.

Anuncios

Este cache al igual que los indices de MyIsam son organizados en bloques, pero que es un bloque? Lo podemos definir como :

Un bloque es la cantidad minima de memoria contigua

El tinchicus
Anuncios

Si bien archivos de indices y los caches de clave pueden tener diferentes tamaños, lo recomendable es que sean multiplos entre si pero lo mas optimo es que posean el mismo tamaño, para definir los tamaños se utilizan las variables:

  • myisam_block_size, para los bloques de los archivos de indices
  • key_cache_block_size, para los bloques del cache de claves
Anuncios

De una manera muy similar a cuando vimos InnoDB, los datos de la cache de claves modificados en memoria se lo denomina bloques sucios y los que no se denomina bloques limpios.

Anuncios
Anuncios

De manera predeterminada este motor utiliza el algoritmo LRU (Menos Usado Recientemente por sus siglas en ingles) para determinar cuales bloques son almacenados en el cache, si bien cuando hablamos en InnoDB sobre este algoritmo no mencionamos el mayor inconveniente que nos genera, si un query realiza un escaneo completo de todos los indices este accedera a bloques con lectura poco frecuente y seran ingresados dentro del cache reemplazando bloques que deberian permanecer en el cache, al igual que en InnoDB una alternativa es dividirlo en dos listas pero aqui se llamaran:

  • Lista calida
  • Lista caliente
Anuncios
Anuncios

La longitud de estas listas no es una variable pero si es el minimo porcentaje de la cache dedicada a la lista calida y este es determinada por la variable key_cache_division_limit, cuando un bloque que no esta en el cache es accedido se lo inserta al final de la lista calida y otros bloques calidos son desplazados al final de la lista, el bloque que esta al comienzo de la lista es el primer candidato a sacarlo de la misma, en cambio si un bloque calido es accedido tres veces se mueve a la lista caliente, otros bloques son movidos al final de la lista y si un bloque permanece por una cierta cantidad de tiempo al final de la lista caliente se la mueve a la lista calida.

Anuncios

En algunas operaciones el cache sera protegido por un mutex, y esto puede ser un problema cuando varias conexiones lo usen al mismo tiempo, para evitar esto tenemos dos mecanismos:

  • Las instancias
  • La segmentacion
Anuncios

En el primer mecanismo cada instancia tiene su propio bloqueo, tambien se pueden configurar individualmente, de manera predeterminada solo la instancia predeterminada de la cache de claves existe, para crearla simplemente debemos establecer a key_buffer_size, veamos su sintaxis:

SET [nombre_instancia.]nombre_variable = valor;
Anuncios

El unico valor opcional es el nombre de la instancia que en caso de no informarse se usara la instancia predeterminada, veamos algunos ejemplos:

MariaDB [(none)]> set @@global.cache_clave_1.key_buffer_size = 20000*1024;
Query OK, 0 rows affected (0.002 sec)

MariaDB [(none)]> set @@global.key_buffer_size = 60000*1024;
Query OK, 0 rows affected (0.009 sec)

MariaDB [(none)]> set @@global.cache_clave_2.key_buffer_size = 20000*1024;
Query OK, 0 rows affected (0.010 sec)

MariaDB [(none)]>
Anuncios

El primer comando creara una instancia llamada cache_clave_1, y tendra un tamaño de 20 MB, en el segundo caso definimos la instancia de la instancia predeterminada y para el tercer caso creamos otra instancia llamada cache_clave_2 con el mismo tamaño de la primera, el mayor inconveniente de hacerlo de esta manera es que las instancias se perderan cuando se reinicien, para evitar ello debemos usar el archivo de configuraciones y en esta agregaremos las siguientes lineas:

cache_clave_1.key_buffer_size = 20480000
key_buffer_size = 61440000
cache_clave_2.key_buffer_size = 20480000
Anuncios

Para saber de las instancias que existen se debe hacer un query en la tabla KEY_CACHES de la base information_schema, veamos el query:

MariaDB [(none)]> select key_cache_name from information_schema.key_caches;
+----------------+
| key_cache_name |
+----------------+
| default        |
| cache_clave_1  |
| cache_clave_2  |
+----------------+
3 rows in set (0.001 sec)

MariaDB [(none)]>
Anuncios

Para eliminar una instancia simplemente establecemos el valor de la misma en cero y desaparecera:

MariaDB [(none)]> set @@global.cache_clave_1.key_buffer_size = 0;
Query OK, 0 rows affected (0.001 sec)

MariaDB [(none)]> select key_cache_name from information_schema.key_caches;
+----------------+
| key_cache_name |
+----------------+
| default        |
| cache_clave_2  |
+----------------+
2 rows in set (0.001 sec)

MariaDB [(none)]>
Anuncios
Nota: 
La unica instancia que no se puede eliminar es la predeterminada.
Anuncios

A continuacion veamos las columnas de la tabla KEY_CACHES:

Anuncios
  • KEY_CACHE_NAME, informa el nombre de la instancia, default identifica a la predeterminada
  • SEGMENTS, este informa el numero de segmentos en la instancia
  • SEGMENT_NUMBER, si esta segmentado cada fila representa un segmento
  • FULL_SIZE, informa el total de memoria utilizado por la memoria
  • BLOCK_SIZE, informa el tamaño de los bloques
  • USED_BLOCKS, informa el numero de bloques usados
  • UNUSED_BLOCKS, informa el numero de bloques libres
  • DIRTY_BLOCKS, informa el numero de bloques sucios
  • READ_REQUESTS, informa las operaciones de lectura pendientes
  • READS, informa el numero de operaciones de copia de los archivos de indice a la instancia
  • WRITE_REQUESTS, informa las operaciones de escritura pendientes
  • WRITES, informa el numero de operaciones de copia de la instancia a los archivos de indice
Anuncios

Si el conjunto de entradas de indices estan ceontenidas en la cache de claves los numeros de lectura y escritura pero particularmente los de lecturas y escrituras pendientes deberian ser minimos especialmente en la actividad de la base de datos, un numero alto de bloques sin usar significa que la instancia esta fragmentada, cada indice puede ser almacenado en un solo cache, los indices de la misma tabla son almacenados en el mismo cache, si tenemos una sola instancia, la predeterminada por ejemplo, no es necesario en cual debe trabajar pero si tenemos mas de una podemos utilizar a CACHE INDEX para especificar en cual instancia debe trabajar, estas asociaciones no son inmutables por lo tanto podemos modificarlo en cualquier momento, veamos un ejemplo:

MariaDB [base1]> cache index tabla4 in cache_clave_2;
Anuncios

Es tan simple como lo ven, usamos el comando seguido de la tabla o tablas que deseamos asignar y por ultimo el nombre de la instancia, si todo sale bien deberan ver lo siguiente:

MariaDB [base1]> cache index tabla4 in cache_clave_2;
+--------------+--------------------+----------+----------+
| Table        | Op                 | Msg_type | Msg_text |
+--------------+--------------------+----------+----------+
| base1.tabla4 | assign_to_keycache | status   | OK       |
+--------------+--------------------+----------+----------+
1 row in set (0.002 sec)

MariaDB [base1]>
Anuncios

Ahora vamos a hablar sobre la segunda mecanica como es la segmentacion, esta es la accion de dividir a la instancia creada anteriormente en varios segmentos, para crearlas usaremos a la variable key_cache_segments la cual representa la cantidad de ellas, su valor maximo es 64, su valor predeterminada es 0 la cual tambien la desactiva, cuando hablamos de las columnas de KEY_CACHES mencionamos a un par que representaban a los segmentos, para entender este concepto vamos a hacer primero este query:

MariaDB [base1]> select
    -> key_cache_name, segments, segment_number, unused_blocks
    -> from information_schema.key_caches;
Anuncios

Lo cual nos devolvera lo siguiente:

+----------------+----------+----------------+---------------+
| key_cache_name | segments | segment_number | unused_blocks |
+----------------+----------+----------------+---------------+
| default        |     NULL |           NULL |         48973 |
| cache_clave_2  |     NULL |           NULL |         16171 |
+----------------+----------+----------------+---------------+
2 rows in set (0.001 sec)
Anuncios

Ahora vamos a segmentar la cache llamada cache_clave_2 mediante el siguiente comando:

MariaDB [base1]> set @@global.cache_clave_2.key_cache_segments = 4;
Anuncios

Ahora si volvemos a ejecutar el query anterior obtendremos la siguiente salida:

MariaDB [base1]> select key_cache_name, segments, segment_number, unused_blocks from information_schema.key_caches;
+----------------+----------+----------------+---------------+
| key_cache_name | segments | segment_number | unused_blocks |
+----------------+----------+----------------+---------------+
| default        |     NULL |           NULL |         48973 |
| cache_clave_2  |        4 |              1 |          4041 |
| cache_clave_2  |        4 |              2 |          4041 |
| cache_clave_2  |        4 |              3 |          4041 |
| cache_clave_2  |        4 |              4 |          4041 |
| cache_clave_2  |        4 |           NULL |         16164 |
+----------------+----------+----------------+---------------+
6 rows in set (0.003 sec)

MariaDB [base1]>
Anuncios

En este caso usamos a UNUSED_BLOCKS para que podamos ver como la suma de los cuatros segmentos es igual al total en la instancia NULL, dado que es la representacion de la misma, por lo tanto ahora la informacion sera distribuida entre las mismas.

Anuncios

Esperar a que los bloques de indices sean leidos durante las actividades normal de la base de datos y luego cargarlas dentro del cache no seria conveniente, para evitar esto se puede precargar indices dentro del cache mediante la ejecucion de comandos o al inicio, para esto podemos usar a LOAD INDEX INTO CACHE para precargar todos los indices de una tabla en su cache asociado o cache predeterminado.

Anuncios

En resumen, hoy hemos visto los caches de MyIsam, cuales son, como se comportan, como se usan, algunas caracteristicas interesantes, y varias formas de trabajar con ellas, espero les haya sido de utilidad sigueme en tumblr, Twitter o Facebook para recibir una notificacion cada vez que subo un nuevo post en este blog, nos vemos en el proximo post.

Anuncios

Donación

Es para mantenimento del sitio, gracias!

$1.50

Anuncio publicitario