Particionamiento de MySQL para Grandes Conjuntos de Datos

MySQLBeginner
Practicar Ahora

Introducción

En este laboratorio, aprenderá a implementar el particionamiento de MySQL para grandes conjuntos de datos con el fin de mejorar el rendimiento de las consultas y la gestión de datos. El laboratorio se centra en particionar una tabla por rango, específicamente utilizando la columna sale_date de una tabla sales.

Comenzará conectándose al servidor MySQL y creando una base de datos sales_data. Luego, creará la tabla sales, particionándola por el año de sale_date en particiones para 2020, 2021, 2022, 2023 y una partición futura. Los pasos subsiguientes cubrirán la consulta de datos de particiones específicas, la reorganización de particiones utilizando ALTER TABLE y la verificación del impacto del particionamiento en la velocidad de las consultas.

Nota: Para este laboratorio, solo necesita ingresar al shell de MySQL una vez al principio y salir al final. Todos los comandos SQL en los siguientes pasos deben ejecutarse dentro de la misma sesión de MySQL.

Este es un Guided Lab, que proporciona instrucciones paso a paso para ayudarte a aprender y practicar. Sigue las instrucciones cuidadosamente para completar cada paso y obtener experiencia práctica. Los datos históricos muestran que este es un laboratorio de nivel principiante con una tasa de finalización del 93%. Ha recibido una tasa de reseñas positivas del 96% por parte de los estudiantes.

Crear una Tabla Particionada

En este paso, crearemos una base de datos y una tabla particionada en MySQL. El particionamiento ayuda a gestionar grandes conjuntos de datos dividiendo una tabla en partes más pequeñas y manejables basándose en una regla especificada. Esto puede mejorar significativamente el rendimiento de las consultas, especialmente para aquellas que filtran datos basándose en la clave de particionamiento.

Primero, abra una terminal en la VM de LabEx. Debería estar en el directorio ~/project.

Conéctese al servidor MySQL como usuario root (haga esto solo una vez al inicio del laboratorio):

sudo mysql -u root

Ahora se encuentra en el shell de MySQL. Todos los comandos SQL subsiguientes deben ejecutarse en esta sesión hasta que finalice el laboratorio.

Creemos una base de datos llamada sales_data para almacenar nuestra tabla:

CREATE DATABASE sales_data;

Cambie a la base de datos recién creada:

USE sales_data;

Ahora, crearemos una tabla llamada sales y la particionaremos por el año de la columna sale_date. Crearemos particiones para los años 2020, 2021, 2022, 2023 y una partición "catch-all" (general) para fechas futuras.

CREATE TABLE sales (
    sale_id INT NOT NULL,
    sale_date DATE NOT NULL,
    amount DECIMAL(10, 2) NOT NULL,
    PRIMARY KEY (sale_id, sale_date)
)
PARTITION BY RANGE (YEAR(sale_date)) (
    PARTITION p2020 VALUES LESS THAN (2021),
    PARTITION p2021 VALUES LESS THAN (2022),
    PARTITION p2022 VALUES LESS THAN (2023),
    PARTITION p2023 VALUES LESS THAN (2024),
    PARTITION pFuture VALUES LESS THAN MAXVALUE
);

Comprendamos la cláusula PARTITION BY RANGE:

  • PARTITION BY RANGE (YEAR(sale_date)): Esto especifica que la tabla se particionará basándose en el rango de valores devueltos por la función YEAR() aplicada a la columna sale_date.
  • PARTITION p2020 VALUES LESS THAN (2021): Esto crea una partición llamada p2020. Cualquier fila donde el año de sale_date sea menor que 2021 (es decir, 2020) se almacenará en esta partición.
  • PARTITION p2021 VALUES LESS THAN (2022): Esto crea una partición llamada p2021 para datos del año 2021.
  • PARTITION p2022 VALUES LESS THAN (2023): Esto crea una partición llamada p2022 para datos del año 2022.
  • PARTITION p2023 VALUES LESS THAN (2024): Esto crea una partición llamada p2023 para datos del año 2023.
  • PARTITION pFuture VALUES LESS THAN MAXVALUE: Esto crea una partición llamada pFuture que almacenará cualquier dato con un año de sale_date mayor o igual a 2024. MAXVALUE es un valor especial que siempre es mayor que cualquier otro valor.

Después de ejecutar la sentencia CREATE TABLE, puede verificar la estructura de la tabla y sus particiones utilizando el siguiente comando:

SHOW CREATE TABLE sales;

Busque la cláusula PARTITION BY RANGE en la salida para confirmar que la tabla se creó con las particiones especificadas.

Ahora, insertemos algunos datos de ejemplo en la tabla sales. MySQL colocará automáticamente cada fila en la partición correcta basándose en sale_date.

INSERT INTO sales (sale_id, sale_date, amount) VALUES
(1, '2020-12-31', 100.00),
(2, '2021-01-15', 150.00),
(3, '2021-12-25', 200.00),
(4, '2022-06-01', 120.00),
(5, '2022-12-31', 180.00),
(6, '2023-03-10', 250.00),
(7, '2023-09-20', 300.00),
(8, '2024-01-01', 350.00);

Ha creado con éxito una tabla particionada e insertado datos en ella. En el siguiente paso, aprenderemos a consultar datos de particiones específicas.

Consultar Datos de Particiones Específicas

En este paso, exploraremos cómo consultar datos de manera eficiente desde una tabla particionada, apuntando a particiones específicas. Este es uno de los principales beneficios del particionamiento, ya que permite a MySQL escanear solo las particiones relevantes, reduciendo significativamente la cantidad de datos procesados y mejorando el rendimiento de las consultas.

Recordatorio: Debería seguir en el shell de MySQL y utilizando la base de datos sales_data. Si no es así, use:

USE sales_data;

Para consultar datos de una partición específica, puede incluir una cláusula WHERE que filtre por la clave de particionamiento. El optimizador de consultas de MySQL suele ser lo suficientemente inteligente como para identificar qué particiones son relevantes basándose en la cláusula WHERE.

Por ejemplo, para recuperar todas las ventas del año 2021, puede usar la siguiente consulta. Tenga en cuenta que estamos utilizando una condición de rango directa en sale_date. El uso de funciones como YEAR(sale_date) en la cláusula WHERE puede impedir que MySQL utilice la poda de particiones (partition pruning), lo que haría que escanee todas las particiones.

SELECT * FROM sales WHERE sale_date >= '2021-01-01' AND sale_date < '2022-01-01';

Para ver qué particiones está accediendo MySQL para esta consulta, puede usar la sentencia EXPLAIN PARTITIONS:

EXPLAIN PARTITIONS SELECT * FROM sales WHERE sale_date >= '2021-01-01' AND sale_date < '2022-01-01';

En la salida de EXPLAIN PARTITIONS, observe la columna partitions. Debería mostrar p2021, lo que indica que MySQL solo está escaneando la partición p2021 para cumplir con esta consulta.

+----+-------------+-------+------------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | sales | p2021      | ALL  | PRIMARY       | NULL | NULL    | NULL |    2 | Using where |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+-------------+

También puede consultar datos que abarcan varias particiones. Por ejemplo, para obtener datos de ventas de 2022 y 2023:

SELECT * FROM sales WHERE sale_date >= '2022-01-01' AND sale_date < '2024-01-01';

Usando EXPLAIN PARTITIONS nuevamente, se mostrará que MySQL accede a las particiones p2022 y p2023:

EXPLAIN PARTITIONS SELECT * FROM sales WHERE sale_date >= '2022-01-01' AND sale_date < '2024-01-01';

La columna partitions mostrará p2022,p2023.

+----+-------------+-------+---------------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | partitions    | type | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+-------+---------------+------+---------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | sales | p2022,p2023   | ALL  | PRIMARY       | NULL | NULL    | NULL |    4 | Using where |
+----+-------------+-------+---------------+------+---------------+------+---------+------+------+-------------+

Esto demuestra cómo el particionamiento permite a MySQL podar (excluir) particiones irrelevantes durante la ejecución de consultas, lo que conduce a resultados más rápidos, especialmente en tablas muy grandes donde escanear la tabla completa sería un proceso largo.

Para ver el número de filas en cada partición, puede consultar la tabla INFORMATION_SCHEMA.PARTITIONS:

SELECT
    PARTITION_NAME,
    TABLE_ROWS
FROM
    INFORMATION_SCHEMA.PARTITIONS
WHERE
    TABLE_SCHEMA = 'sales_data' AND TABLE_NAME = 'sales';

Esta consulta proporciona una visión clara de cómo se distribuyen los datos en sus particiones.

+----------------+------------+
| PARTITION_NAME | TABLE_ROWS |
+----------------+------------+
| p2020          |          1 |
| p2021          |          2 |
| p2022          |          2 |
| p2023          |          2 |
| pFuture        |          1 |
+----------------+------------+

Ha consultado con éxito datos de particiones específicas y ha observado cómo MySQL utiliza el particionamiento para la optimización de consultas.

Reorganizar y Gestionar Particiones

En este paso, aprenderemos cómo modificar la estructura de partición de una tabla existente utilizando la sentencia ALTER TABLE. Esto es útil para adaptar su esquema de particionamiento a medida que sus datos crecen o sus necesidades cambian.

Recordatorio: Debería seguir en el shell de MySQL y utilizando la base de datos sales_data. Si no es así, use:

USE sales_data;

Supongamos que queremos agregar una nueva partición para el año 2024. Actualmente, los datos de 2024 en adelante se encuentran en la partición pFuture. No puede agregar una nueva partición con ADD PARTITION porque la partición pFuture está definida con VALUES LESS THAN MAXVALUE, que siempre debe ser la última partición.

En su lugar, necesitamos REORGANIZE (reorganizar) la partición pFuture para dividirla. Dividiremos pFuture en dos nuevas particiones: una para el año 2024 (p2024) y una nueva partición pFuture para todo lo posterior a esa fecha.

ALTER TABLE sales REORGANIZE PARTITION pFuture INTO (
    PARTITION p2024 VALUES LESS THAN (2025),
    PARTITION pFuture VALUES LESS THAN MAXVALUE
);

Este comando toma la partición pFuture existente, mueve cualquier dato de 2024 a la nueva partición p2024 y redefine pFuture para cubrir las fechas a partir de 2025. La fila con sale_date '2024-01-01' se moverá a p2024.

Verifiquemos la estructura de partición actualizada y los recuentos de filas:

SELECT
    PARTITION_NAME,
    TABLE_ROWS
FROM
    INFORMATION_SCHEMA.PARTITIONS
WHERE
    TABLE_SCHEMA = 'sales_data' AND TABLE_NAME = 'sales';

Debería ver la nueva partición p2024. La fila de 2024 ahora está en p2024.

+----------------+------------+
| PARTITION_NAME | TABLE_ROWS |
+----------------+------------+
| p2020          |          0 |
| p2021          |          2 |
| p2022          |          2 |
| p2023          |          2 |
| p2024          |          0 |
| pFuture        |          0 |
+----------------+------------+

Ahora, demostremos la fusión de particiones. Supongamos que queremos combinar las particiones p2020 y p2021 en una sola partición llamada p2020_2021.

ALTER TABLE sales REORGANIZE PARTITION p2020, p2021 INTO (
    PARTITION p2020_2021 VALUES LESS THAN (2022)
);

Este comando fusiona los datos de p2020 y p2021 en una nueva partición llamada p2020_2021. La cláusula VALUES LESS THAN (2022) define el nuevo límite para esta partición fusionada.

Verifique la estructura de partición nuevamente:

SELECT
    PARTITION_NAME,
    TABLE_ROWS
FROM
    INFORMATION_SCHEMA.PARTITIONS
WHERE
    TABLE_SCHEMA = 'sales_data' AND TABLE_NAME = 'sales';

Verá que p2020 y p2021 ya no existen, y p2020_2021 aparece con el recuento de filas combinado.

+----------------+------------+
| PARTITION_NAME | TABLE_ROWS |
+----------------+------------+
| p2020_2021     |          3 |
| p2022          |          2 |
| p2023          |          2 |
| p2024          |          0 |
| pFuture        |          0 |
+----------------+------------+

Finalmente, eliminemos una partición. Podemos eliminar la partición p2024. Tenga en cuenta que esto también eliminará todos los datos dentro de esa partición.

ALTER TABLE sales DROP PARTITION p2024;

Verifique la estructura de partición una última vez:

SELECT
    PARTITION_NAME,
    TABLE_ROWS
FROM
    INFORMATION_SCHEMA.PARTITIONS
WHERE
    TABLE_SCHEMA = 'sales_data' AND TABLE_NAME = 'sales';

La partición p2024 ya no debería aparecer en la lista.

+----------------+------------+
| PARTITION_NAME | TABLE_ROWS |
+----------------+------------+
| p2020_2021     |          3 |
| p2022          |          2 |
| p2023          |          2 |
| pFuture        |          0 |
+----------------+------------+

Ha reorganizado, fusionado y eliminado particiones con éxito utilizando ALTER TABLE. Esto demuestra la flexibilidad de gestionar tablas particionadas a medida que evolucionan sus datos.

Comprobar el Impacto de las Particiones en la Velocidad de Consulta

En este paso, exploraremos cómo el particionamiento puede afectar el rendimiento de las consultas. Aunque nuestro conjunto de datos actual es pequeño, aún podemos observar el principio de la poda de particiones (partition pruning), donde MySQL solo escanea las particiones necesarias. Para conjuntos de datos más grandes, este efecto es mucho más pronunciado.

Recordatorio: Debería seguir en el shell de MySQL y utilizando la base de datos sales_data. Si no es así, use:

USE sales_data;

Para observar el impacto del particionamiento, podemos usar la sentencia EXPLAIN, que muestra el plan de ejecución de una consulta. Específicamente, EXPLAIN PARTITIONS mostrará qué particiones se están accediendo.

Ejecutemos una consulta que filtre por la clave de particionamiento (año de sale_date):

EXPLAIN PARTITIONS SELECT * FROM sales WHERE sale_date >= '2023-01-01' AND sale_date < '2024-01-01';

Observe la columna partitions en la salida. Debería indicar que solo se está escaneando la partición p2023.

Ahora, ejecutemos una consulta que no filtre directamente por la clave de particionamiento, sino por otra columna (amount):

EXPLAIN PARTITIONS SELECT * FROM sales WHERE amount > 200;

En este caso, dado que la condición de la consulta no está directamente sobre la clave de particionamiento (sale_date), MySQL podría necesitar escanear múltiples o todas las particiones para encontrar las filas coincidentes. La columna partitions en la salida de EXPLAIN PARTITIONS mostrará qué particiones fueron consideradas. Con nuestro pequeño conjunto de datos, es posible que aún escanee todas las particiones.

Para obtener una visión más detallada del proceso de ejecución de la consulta y el tiempo empleado, puede utilizar la función de perfilado (profiling) de MySQL.

Habilitar el perfilado:

SET profiling = 1;

Ahora, ejecute las dos consultas nuevamente:

SELECT * FROM sales WHERE sale_date >= '2023-01-01' AND sale_date < '2024-01-01';
SELECT * FROM sales WHERE amount > 200;

Vea los resultados del perfilado:

SHOW PROFILES;

La salida listará las consultas ejecutadas y su duración. Luego puede examinar los detalles de una consulta específica usando su Query_ID:

SHOW PROFILE FOR QUERY [Query_ID];

Reemplace [Query_ID] con el ID de la consulta que desea analizar de la salida de SHOW PROFILES. Observe las diferentes etapas de ejecución y el tiempo dedicado a cada una.

Aunque la diferencia de tiempo podría ser insignificante con nuestro pequeño conjunto de datos, en un escenario del mundo real con millones de filas, las consultas que pueden utilizar la poda de particiones (como la que filtra por YEAR(sale_date)) serán significativamente más rápidas que aquellas que necesitan escanear múltiples o todas las particiones.

Finalmente, desactive el perfilado:

SET profiling = 0;

Este paso demostró cómo usar EXPLAIN PARTITIONS y el perfilado para comprender cómo el particionamiento afecta la ejecución y el rendimiento de las consultas.

Resumen

En este laboratorio, ha aprendido a implementar el particionamiento de MySQL para grandes conjuntos de datos con el fin de mejorar el rendimiento de las consultas y la gestión de datos. Comenzó creando una base de datos y una tabla particionada por rango según el año de una columna de fecha. Luego practicó la consulta de datos de particiones específicas, observando cómo MySQL utiliza la poda de particiones (partition pruning) para optimizar las consultas. Finalmente, aprendió a reorganizar particiones agregando, dividiendo y fusionando mediante la sentencia ALTER TABLE, y exploró cómo usar EXPLAIN PARTITIONS y el perfilado para comprender el impacto del particionamiento en la velocidad de las consultas. El particionamiento es una técnica poderosa para gestionar y consultar tablas grandes de manera eficiente en MySQL.

Cuando haya completado todos los pasos, puede salir del shell de MySQL escribiendo:

exit;