sql >> Base de Datos >  >> RDS >> MariaDB

Manejo de grandes volúmenes de datos con MySQL y MariaDB

La mayoría de las bases de datos aumentan de tamaño con el tiempo. El crecimiento no siempre es lo suficientemente rápido como para afectar el rendimiento de la base de datos, pero definitivamente hay casos en los que eso sucede. Cuando sucede, a menudo nos preguntamos qué se podría hacer para reducir ese impacto y cómo podemos garantizar operaciones de base de datos fluidas cuando se trata de datos a gran escala.

En primer lugar, intentemos definir qué significa un "gran volumen de datos". Para MySQL o MariaDB es InnoDB sin comprimir. InnoDB funciona de una manera que se beneficia enormemente de la memoria disponible, principalmente el grupo de búfer de InnoDB. Siempre que los datos quepan allí, el acceso al disco se minimiza para manejar solo escrituras; las lecturas se sirven fuera de la memoria. ¿Qué sucede cuando los datos superan la memoria? Cada vez se deben leer más datos del disco cuando es necesario acceder a las filas, que actualmente no están almacenadas en caché. Cuando aumenta la cantidad de datos, la carga de trabajo cambia de un límite de CPU a un límite de E/S. Significa que el cuello de botella ya no es la CPU (que era el caso cuando los datos caben en la memoria; el acceso a los datos en la memoria es rápido, la transformación y agregación de datos es más lenta), sino el subsistema de E/S (las operaciones de la CPU en los datos son mucho más lentas). más rápido que acceder a los datos desde el disco). Con una mayor adopción de flash, las cargas de trabajo vinculadas a E/S no son tan terribles como solían ser en los tiempos de las unidades giratorias (el acceso aleatorio es mucho más rápido con SSD), pero el impacto en el rendimiento sigue ahí. .

Otra cosa que debemos tener en cuenta es que, por lo general, solo nos preocupamos por el conjunto de datos activo. Claro, es posible que tenga terabytes de datos en su esquema, pero si tiene que acceder solo a los últimos 5 GB, esta es una situación bastante buena. Claro, todavía plantea desafíos operativos, pero en cuanto al rendimiento, debería estar bien.

Supongamos para el propósito de este blog, y esta no es una definición científica, que por el gran volumen de datos nos referimos a un caso en el que el tamaño de los datos activos supera significativamente el tamaño de la memoria. Puede ser de 100 GB cuando tiene 2 GB de memoria, puede ser de 20 TB cuando tiene 200 GB de memoria. El punto de inflexión es que su carga de trabajo está estrictamente limitada a E/S. Tenga paciencia mientras discutimos algunas de las opciones disponibles para MySQL y MariaDB.

Particionamiento

El enfoque histórico (pero perfectamente válido) para manejar grandes volúmenes de datos es implementar la partición. La idea detrás de esto es dividir la tabla en particiones, una especie de subtablas. La división ocurre de acuerdo con las reglas definidas por el usuario. Echemos un vistazo a algunos de los ejemplos (los ejemplos de SQL están tomados de la documentación de MySQL 8.0)

MySQL 8.0 viene con los siguientes tipos de partición:

  • RANGO
  • LISTA
  • COLUMNAS
  • HASH
  • CLAVE

También puede crear subparticiones. No vamos a volver a escribir la documentación aquí, pero aun así nos gustaría darle una idea de cómo funcionan las particiones. Para crear particiones, debe definir la clave de partición. Puede ser una columna o, en el caso de RANGE o LIST, varias columnas que se utilizarán para definir cómo se deben dividir los datos en particiones.

La partición HASH requiere que el usuario defina una columna, que será codificada. Luego, los datos se dividirán en un número de particiones definido por el usuario en función de ese valor hash:

CREATE TABLE employees (
    id INT NOT NULL,
    fname VARCHAR(30),
    lname VARCHAR(30),
    hired DATE NOT NULL DEFAULT '1970-01-01',
    separated DATE NOT NULL DEFAULT '9999-12-31',
    job_code INT,
    store_id INT
)
PARTITION BY HASH( YEAR(hired) )
PARTITIONS 4;

En este caso, se creará un hash en función del resultado generado por la función AÑO() en la columna "contratado".

El particionamiento de KEY es similar, con la excepción de que el usuario define qué columna se debe codificar y el resto depende de que MySQL lo maneje.

Mientras que las particiones HASH y KEY distribuyen aleatoriamente los datos entre el número de particiones, RANGE y LIST permiten al usuario decidir qué hacer. RANGO se usa comúnmente con la hora o la fecha:

CREATE TABLE quarterly_report_status (
    report_id INT NOT NULL,
    report_status VARCHAR(20) NOT NULL,
    report_updated TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
)
PARTITION BY RANGE ( UNIX_TIMESTAMP(report_updated) ) (
    PARTITION p0 VALUES LESS THAN ( UNIX_TIMESTAMP('2008-01-01 00:00:00') ),
    PARTITION p1 VALUES LESS THAN ( UNIX_TIMESTAMP('2008-04-01 00:00:00') ),
    PARTITION p2 VALUES LESS THAN ( UNIX_TIMESTAMP('2008-07-01 00:00:00') ),
    PARTITION p3 VALUES LESS THAN ( UNIX_TIMESTAMP('2008-10-01 00:00:00') ),
    PARTITION p4 VALUES LESS THAN ( UNIX_TIMESTAMP('2009-01-01 00:00:00') ),
    PARTITION p5 VALUES LESS THAN ( UNIX_TIMESTAMP('2009-04-01 00:00:00') ),
    PARTITION p6 VALUES LESS THAN ( UNIX_TIMESTAMP('2009-07-01 00:00:00') ),
    PARTITION p7 VALUES LESS THAN ( UNIX_TIMESTAMP('2009-10-01 00:00:00') ),
    PARTITION p8 VALUES LESS THAN ( UNIX_TIMESTAMP('2010-01-01 00:00:00') ),
    PARTITION p9 VALUES LESS THAN (MAXVALUE)
);

También se puede utilizar con otro tipo de columnas:

CREATE TABLE employees (
    id INT NOT NULL,
    fname VARCHAR(30),
    lname VARCHAR(30),
    hired DATE NOT NULL DEFAULT '1970-01-01',
    separated DATE NOT NULL DEFAULT '9999-12-31',
    job_code INT NOT NULL,
    store_id INT NOT NULL
)
PARTITION BY RANGE (store_id) (
    PARTITION p0 VALUES LESS THAN (6),
    PARTITION p1 VALUES LESS THAN (11),
    PARTITION p2 VALUES LESS THAN (16),
    PARTITION p3 VALUES LESS THAN MAXVALUE
);

Las particiones LIST funcionan en función de una lista de valores que ordena las filas en varias particiones:

CREATE TABLE employees (
    id INT NOT NULL,
    fname VARCHAR(30),
    lname VARCHAR(30),
    hired DATE NOT NULL DEFAULT '1970-01-01',
    separated DATE NOT NULL DEFAULT '9999-12-31',
    job_code INT,
    store_id INT
)
PARTITION BY LIST(store_id) (
    PARTITION pNorth VALUES IN (3,5,6,9,17),
    PARTITION pEast VALUES IN (1,2,10,11,19,20),
    PARTITION pWest VALUES IN (4,12,13,14,18),
    PARTITION pCentral VALUES IN (7,8,15,16)
);

¿Cuál es el punto en el uso de particiones que usted puede pedir? El punto principal es que las búsquedas son significativamente más rápidas que con una tabla sin particiones. Supongamos que desea buscar las filas que se crearon en un mes determinado. Si tiene varios años de datos almacenados en la tabla, esto será un desafío:se deberá usar un índice y, como sabemos, los índices ayudan a encontrar filas, pero acceder a esas filas resultará en un montón de lecturas aleatorias de toda la mesa. Si tiene particiones creadas mes a año, MySQL puede simplemente leer todas las filas de esa partición en particular; no es necesario acceder al índice, no es necesario realizar lecturas aleatorias:simplemente lea todos los datos de la partición, secuencialmente, y estamos todo listo.

Las particiones también son muy útiles para lidiar con la rotación de datos. Si MySQL puede identificar fácilmente las filas para eliminarlas y asignarlas a una sola partición, en lugar de ejecutar DELETE FROM table WHERE..., que usará el índice para ubicar las filas, puede truncar la partición. Esto es extremadamente útil con el particionamiento RANGE:siguiendo el ejemplo anterior, si queremos conservar los datos solo durante 2 años, podemos crear fácilmente un trabajo cron, que eliminará la partición anterior y creará una nueva vacía para el próximo mes.

Compresión InnoDB

Si tenemos un gran volumen de datos (no necesariamente pensando en bases de datos), lo primero que se nos viene a la cabeza es comprimirlos. Existen numerosas herramientas que brindan una opción para comprimir sus archivos, reduciendo significativamente su tamaño. InnoDB también tiene una opción para eso:tanto MySQL como MariaDB admiten la compresión InnoDB. La principal ventaja de utilizar la compresión es la reducción de la actividad de E/S. Los datos, cuando se comprimen, son más pequeños, por lo que son más rápidos de leer y escribir. La página típica de InnoDB tiene un tamaño de 16 KB, para SSD son 4 operaciones de E/S para leer o escribir (SSD normalmente usa páginas de 4 KB). Si logramos comprimir 16 KB en 4 KB, solo redujimos las operaciones de E/S en cuatro. Realmente no ayuda mucho con respecto a la relación entre el conjunto de datos y la memoria. En realidad, incluso puede empeorar las cosas:MySQL, para operar con los datos, tiene que descomprimir la página. Sin embargo, lee la página comprimida del disco. Esto da como resultado que el grupo de búfer de InnoDB almacene 4 KB de datos comprimidos y 16 KB de datos sin comprimir. Por supuesto, existen algoritmos para eliminar datos innecesarios (la página sin comprimir se eliminará cuando sea posible, manteniendo solo una comprimida en la memoria), pero no puede esperar demasiada mejora en esta área.

También es importante tener en cuenta cómo funciona la compresión con respecto al almacenamiento. Las unidades de estado sólido son la norma para los servidores de bases de datos en estos días y tienen un par de características específicas. Son rápidos, no les importa mucho si el tráfico es secuencial o aleatorio (aunque todavía prefieren el acceso secuencial al aleatorio). Son caros para grandes volúmenes. Sufren de "desgaste" ya que pueden manejar un número limitado de ciclos de escritura. La compresión ayuda significativamente aquí:al reducir el tamaño de los datos en el disco, reducimos el costo de la capa de almacenamiento para la base de datos. Al reducir el tamaño de los datos que escribimos en el disco, aumentamos la vida útil del SSD.

Desafortunadamente, incluso si la compresión ayuda, para grandes volúmenes de datos puede no ser suficiente. Otro paso sería buscar algo más que InnoDB.

MisRocas

MyRocks es un motor de almacenamiento disponible para MySQL y MariaDB que se basa en un concepto diferente al de InnoDB. Mi colega, Sebastian Insausti, tiene un buen blog sobre el uso de MyRocks con MariaDB. La esencia es que, debido a su diseño (utiliza Log Structured Merge, LSM), MyRocks es significativamente mejor en términos de compresión que InnoDB (que se basa en la estructura B+Tree). MyRocks está diseñado para manejar grandes cantidades de datos y reducir el número de escrituras. Se originó en Facebook, donde los volúmenes de datos son grandes y los requisitos para acceder a los datos son altos. Por lo tanto, el almacenamiento SSD, aún así, a una escala tan grande, cada ganancia en compresión es enorme. MyRocks puede ofrecer hasta 2 veces mejor compresión que InnoDB (lo que significa que reduce la cantidad de servidores en dos). También está diseñado para reducir la amplificación de escritura (cantidad de escrituras requeridas para manejar un cambio en el contenido de la fila); requiere 10 veces menos escrituras que InnoDB. Obviamente, esto reduce la carga de E/S pero, lo que es más importante, aumentará diez veces la vida útil de un SSD en comparación con manejar la misma carga con InnoDB). Desde el punto de vista del rendimiento, cuanto menor sea el volumen de datos, más rápido será el acceso, por lo que los motores de almacenamiento como ese también pueden ayudar a sacar los datos de la base de datos más rápido (aunque no era la máxima prioridad al diseñar MyRocks).

Almacenes de datos en columnas

Recursos relacionados ClusterControl Performance Management Comprender los efectos de la alta latencia en soluciones MySQL y MariaDB de alta disponibilidad Hoja de referencia de rendimiento de MySQL

En algún momento, todo lo que podemos hacer es admitir que no podemos manejar tal volumen de datos usando MySQL. Claro, puedes fragmentarlo, puedes hacer cosas diferentes, pero eventualmente ya no tiene sentido. Es hora de buscar soluciones adicionales. Una de ellas sería utilizar almacenes de datos en columnas:bases de datos diseñadas teniendo en cuenta el análisis de big data. Claro, no ayudarán con el tipo de tráfico OLTP, pero los análisis son bastante estándar hoy en día, ya que las empresas intentan basarse en datos y tomar decisiones basadas en números exactos, no en datos aleatorios. Existen numerosos almacenes de datos en columnas, pero nos gustaría mencionar aquí dos de ellos. MariaDB AX y ClickHouse. Tenemos un par de blogs que explican qué es MariaDB AX y cómo se puede usar MariaDB AX. Lo que es importante, MariaDB AX se puede escalar en forma de clúster, lo que mejora el rendimiento. ClickHouse es otra opción para ejecutar análisis:ClickHouse se puede configurar fácilmente para replicar datos de MySQL, como comentamos en una de nuestras publicaciones de blog. Es rápido, gratuito y también se puede utilizar para formar un clúster y fragmentar datos para obtener un rendimiento aún mejor.

Conclusión

Esperamos que esta publicación de blog le haya brindado información sobre cómo se pueden manejar grandes volúmenes de datos en MySQL o MariaDB. Afortunadamente, hay un par de opciones a nuestra disposición y, eventualmente, si no podemos hacer que funcione, existen buenas alternativas.