sábado, 12 de diciembre de 2009

Fragmentación en MySQL

Al utilizar comandos de fragmentado a nivel de tablas, mysqld utiliza una clave de partición y un algoritmo de particionado para determinar la división de los datos entre los fragmentos. Los algoritmos de fragmentación que tenemos son:

RANGE: Si la clave de fragmentación está dentro de un rango de valores.
LIST: El fragmento es seleccionado de acuerdo a una lista de valores enteros.
HASH: El fragmento se elige de acuerdo a una función de hash.
KEY: Un algoritmo interno es utilizado por mysqld para elegir como serán distribuidos los datos entre los fragmentos.
*Particionado compuesto: Las particiones de RANGE y LIST pueden ser subfragmentadas usando el fragmentado HASH, y KEY.

Fragmentado RANGE (Por rango de valores)

Suponiendo que tenemos la siguiente tabla definida:

CREATE TABLE empleados (
Id_empleado INT NOT NULL,
nombre VARCHAR(30) NOT NULL,
apellidos VARCHAR(30) NOT NULL,
fecha_inicio DATE NOT NULL DEFAULT ’2000-01-01’,
fecha_termino DATE DEFAULT NULL,
salario DECIMAL (8,2) NOT NULL,
codigo_de_trabajo INT NOT NULL,
id_almacenamiento INT NOT NULL
);

Suponiendo que queremos almacenar los datos de 300 empleados en tres tablas de a 100 cada una, procedemos con la siguiente instrucción:

ALTER TABLE empleados
PARTITION BY RANGE (id_almacenamiento) (
PARTITION p0 VALUES LESS THAN (101),
PARTITION p1 VALUES LESS THAN (201),
PARTITION p2 VALUES LESS THAN (301),
PARTITION pfinal VALUES LESS THAN MAXVALUE
);

Esta instrucción utiliza el atributo id_almacenamiento como clave de fragmentado (partition key), y las particiones son p0, p1, p2, y pfinal, en este caso las tres particiones corresponden a los registros en el rango desde 0 hasta 300, pero la partición final es en el caso de que quisiéramos insertar un registro con un valor mayor a 300, lo cual nos generaría un error como el siguiente:

ERROR 1526 (HY000): Table has no partition for value 301.

Si desde la definición de la tabla queremos especificar un esquema de fragmentado, usaríamos la siguiente instrucción:

CREATE TABLE empleados (
Id_empleado INT NOT NULL,
nombre VARCHAR(30) NOT NULL,
apellidos VARCHAR(30) NOT NULL,
fecha_inicio DATE NOT NULL DEFAULT ’2000-01-01’,
fecha_termino DATE DEFAULT NULL,
salario DECIMAL (8,2) NOT NULL,
codigo_de_trabajo INT NOT NULL,
id_almacenamiento INT NOT NULL
)
PARTITION BY RANGE (id_almacenamiento) (
PARTITION p0 VALUES LESS THAN (101),
PARTITION p1 VALUES LESS THAN (201),
PARTITION p2 VALUES LESS THAN (301),
PARTITION pfinal VALUES LESS THAN MAXVALUE
);

Fragmentado LIST (Por lista definida)

Suponiendo que ahora tenemos la misma tabla, pero lo que queremos es distribuir a los empleados de acuerdo a una lista de valores definida, los valores se distribuiran de acuerdo a los valores definidos en cada lista de cada partición.

CREATE TABLE empleados (
Id_empleado INT NOT NULL,
nombre VARCHAR(30) NOT NULL,
apellidos VARCHAR(30) NOT NULL,
fecha_inicio DATE NOT NULL DEFAULT ’2000-01-01’,
fecha_termino DATE DEFAULT NULL,
salario DECIMAL (8,2) NOT NULL,
codigo_de_trabajo INT NOT NULL,
id_almacenamiento INT NOT NULL
)
PARTITION BY LIST (
id_almacenamiento) (
PARTITION Sureste VALUES IN (1,2,3,4,5,6,7,8,9,10,15,17,18,20,21,24),
PARTITION AtlanticoMedio VALUES IN (11,12,13,14,16,19,22,23,25,26,27,28),
PARTITION Noreste VALUES IN (29,30,33,38,40,41,50,56,64,65,75),
PARTITION EsteMedio VALUES IN (32,34,35,42,43,49,51,61,62,63,71),
PARTITION Noroeste VALUES IN (46,53,58,67,68,69,72,74),
PARTITION Canada VALUES IN (31,47,52,59,73),
PARTITION Inlaterra VALUES IN (39,55)
);

Fragmentado HASH (Por dispersión)

En este caso, la distribución de los datos entre un numero x de fragmentos es con el uso del operador residuo (%)

CREATE TABLE empleados (
Id_empleado INT NOT NULL,
nombre VARCHAR(30) NOT NULL,
apellidos VARCHAR(30) NOT NULL,
fecha_inicio DATE NOT NULL DEFAULT ’2000-01-01’,
fecha_termino DATE DEFAULT NULL,
salario DECIMAL (8,2) NOT NULL,
codigo_de_trabajo INT NOT NULL,
id_almacenamiento INT NOT NULL
)
PARTITION BY HASH (
id_almacenamiento)
PARTITIONS 16;


Fragmentado KEY (Fragmentado por clave)

El funcionamiento de este fragmentado es similar al de HASH, la gran diferencia es el algoritmo, que es similar al de la funcion PASSWORD(), y tiene el siguiente cambio respecto a la consulta anterior.

CREATE TABLE empleados (
Id_empleado INT NOT NULL,
nombre VARCHAR(30) NOT NULL,
apellidos VARCHAR(30) NOT NULL,
fecha_inicio DATE NOT NULL DEFAULT ’2000-01-01’,
fecha_termino DATE DEFAULT NULL,
salario DECIMAL (8,2) NOT NULL,
codigo_de_trabajo INT NOT NULL,
id_almacenamiento INT NOT NULL
)
PARTITION BY HASH (
id_almacenamiento)
PARTITIONS 16;


Los casos anteriores de fragmentación son para la Fragmentación Horizontal,

Ahora la fragmentación vertical o también conocida como División de Filas ( row splitting ), ya que los datos de un registro, se almacenan en dos o mas tablas se realiza no por el RDBMS propiamente sino por el administrador o programador.


La implementación de este tipo de fragmentación es guardando el mismo identificador del registro en las dos tablas y los atributos en su tabla correspondiente, o partiendo de un conjunto de datos estaticos, donde una tabla ya definida y con sus registros se divide mediante algun procedimiento almacenados.
La mejor practica, en mi opinión personal es usar la primera forma, que depende más de un programador.

Librito sagrado:
MySQL Administrator’s Bible
Sheeri Cabral, Keith Murphy
Wiley Publishing, Inc.

1 comentario: