particiones en mysql y oracle

5
Particiones en MySQL y Oracle Particiones en MySQL Particionar tablas en MySQL nos permite rotar la información de nuestras tablas en diferentes particiones, consiguiendo así realizar consultas más rápidas y recuperar espacio en disco al borrar los registros. El uso más común de particionado es según fecha (date). Para ver si nuestra base de datos soporta particionado simplemente ejecutamos: SHOW VARIABLES LIKE '%partition%'; A continuación veremos un ejemplo de cómo particionar una tabla por mes y posteriormente borrar o modificar su información. Crear particiones 1.- Creamos la tabla reports : CREATE TABLE reports ( id int(10) NOT NULL AUTO_INCREMENT, date datetime NOT NULL, report TEXT, PRIMARY KEY (id,date) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 Como se puede ver hemos añadido como índice de tabla el campo date , esto es necesario si luego queremos particionar por fecha. 2.- Ahora que tenemos la tabla creada vamos a particionar por mes: ALTER TABLE reports PARTITION BY RANGE(TO_DAYS(date))( PARTITION p201111 VALUES LESS THAN (TO_DAYS("2011-12-01")), PARTITION p201112 VALUES LESS THAN (TO_DAYS("2012-01-01")), PARTITION p201201 VALUES LESS THAN (TO_DAYS("2012-02-01")), PARTITION p201202 VALUES LESS THAN (TO_DAYS("2012-03-01")), PARTITION p201203 VALUES LESS THAN (TO_DAYS("2012-04-01")), PARTITION p201204 VALUES LESS THAN (TO_DAYS("2012-05-01")), PARTITION p201205 VALUES LESS THAN (TO_DAYS("2012-06-01")), PARTITION pDefault VALUES LESS THAN MAXVALUE ); La última partición ( pDefault ) tendrá todos los registros que no entren en las particiones anteriores. De esta manera nos aseguramos que la información nunca dejará de insertarse en la tabla. Borrar particiones Lo bueno de trabajar con particiones es que podemos borrar rápidamente registros sin tener que recorrer toda la tabla e inmediatamente recuperar el espacio en disco utilizado por la tabla. Por ejemplo si queremos borrar la partición más antigua simplemente ejecutamos: ALTER TABLE reports DROP PARTITION p201111;

Upload: xavi-flores

Post on 19-Jan-2016

17 views

Category:

Documents


1 download

TRANSCRIPT

Page 1: Particiones en MySQL y Oracle

Particiones en MySQL y OracleParticiones en MySQLParticionar tablas en MySQL nos permite rotar la información de nuestras tablas en diferentes particiones, consiguiendo así realizar consultas más rápidas y recuperar espacio en disco al borrar los registros. El uso más común de particionado es según fecha (date).Para ver si nuestra base de datos soporta particionado simplemente ejecutamos:

SHOW VARIABLES LIKE '%partition%';

A continuación veremos un ejemplo de cómo particionar una tabla por mes y posteriormente borrar o modificar su información.

Crear particiones

1.- Creamos la tabla reports:CREATE TABLE reports ( id int(10) NOT NULL AUTO_INCREMENT, date datetime NOT NULL, report TEXT, PRIMARY KEY (id,date)) ENGINE=InnoDB DEFAULT CHARSET=utf8

Como se puede ver hemos añadido como índice de tabla el campo date, esto es necesario si luego queremos particionar por fecha.

2.- Ahora que tenemos la tabla creada vamos a particionar por mes:

ALTER TABLE reports PARTITION BY RANGE(TO_DAYS(date))( PARTITION p201111 VALUES LESS THAN (TO_DAYS("2011-12-01")), PARTITION p201112 VALUES LESS THAN (TO_DAYS("2012-01-01")), PARTITION p201201 VALUES LESS THAN (TO_DAYS("2012-02-01")), PARTITION p201202 VALUES LESS THAN (TO_DAYS("2012-03-01")), PARTITION p201203 VALUES LESS THAN (TO_DAYS("2012-04-01")), PARTITION p201204 VALUES LESS THAN (TO_DAYS("2012-05-01")), PARTITION p201205 VALUES LESS THAN (TO_DAYS("2012-06-01")), PARTITION pDefault VALUES LESS THAN MAXVALUE);

La última partición (pDefault) tendrá todos los registros que no entren en las particiones anteriores. De esta manera nos aseguramos que la información nunca dejará de insertarse en la tabla.

Borrar particiones

Lo bueno de trabajar con particiones es que podemos borrar rápidamente registros sin tener que recorrer toda la tabla e inmediatamente recuperar el espacio en disco utilizado por la tabla.Por ejemplo si queremos borrar la partición más antigua simplemente ejecutamos:

ALTER TABLE reports DROP PARTITION p201111;

Añadir particiones

En el ejemplo anterior las 2 últimas particiones creadas han sido:

Page 2: Particiones en MySQL y Oracle

PARTITION p201205 VALUES LESS THAN (TO_DAYS("2012-06-01")),PARTITION pDefault VALUES LESS THAN MAXVALUE

El problema es que todos los INSERTs que se hagan después de mayo de 2012 se insertarán en pDefault. La solución sería añadir particiones nuevas para cubrir los próximos meses:ALTER TABLE reports REORGANIZE PARTITION pDefault INTO (PARTITION p201206 VALUES LESS THAN (TO_DAYS("2012-07-01")),PARTITION pDefault VALUES LESS THAN MAXVALUE);

En el caso que no tuvieramos una partición del tipo pDefault simplemente ejecutamos:ALTER TABLE reports ADD PARTITION (PARTITION p201206 VALUES LESS THAN (TO_DAYS("2012-07-01")));

Consultar particiones

Para consultar información de particiones creadas en una tabla así como también los registros que contiene cada una ejecutamos:SELECT PARTITION_NAME,TABLE_ROWS FROM information_schema.PARTITIONS WHERE TABLE_NAME='reports';  --------------------------------------------------------------

Por rango: para construir nuestras particiones especificamos rangos de valores.

Por ejemplo, podríamos segmentar los datos en 12 particiones: una para los

contratos de 1950 a 1960, otra para los años 60, los 70, 80, 90, la década del

2000 y la década actual

view plaincopy to clipboardprint?

1. ALTER TABLE contratos  2. PARTITION BY RANGE(YEAR(fechaInicio)) (  3.     PARTITION partDecada50 VALUES LESS THAN (1960),  4.     PARTITION partDecada60 VALUES LESS THAN (1970),  5.     PARTITION partDecada70 VALUES LESS THAN (1980),  6.     PARTITION partDecada80 VALUES LESS THAN (1990),  7.     PARTITION partDecada90 VALUES LESS THAN (2000),  8.     PARTITION partDecada00 VALUES LESS THAN (2010),  9.     PARTITION partDecada10 VALUES LESS THAN MAXVALUE  10. );  

Por listas: para construir nuestras particiones especificamos listas de valores

concretos.

view plaincopy to clipboardprint?

1. ALTER TABLE contratos  2. PARTITION BY LIST(YEAR(fechaInicio)) (  3.     PARTITION partDecada50 VALUES IN (1950, 1951, 1952, 1953, 1954, 19

55, 1956, 1957, 1958, 1959),  4.     PARTITION partDecada60 VALUES IN (1960, 1961, 1962, 1963, 1964, 19

65, 1966, 1967, 1968, 1969),  5.     PARTITION partDecada70 VALUES IN (1970, 1971, 1972, 1973, 1974, 19

75, 1976, 1977, 1978, 1979),  

Page 3: Particiones en MySQL y Oracle

6.     PARTITION partDecada80 VALUES IN (1980, 1981, 1982, 1983, 1984, 1985, 1986, 1987, 1988, 1989),  

7.     PARTITION partDecada90 VALUES IN (1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999),  

8.     PARTITION partDecada00 VALUES IN (2000, 2001, 2002, 2003, 2004, 2005, 2006,  

9. 2007, 2008, 2009),  10.     PARTITION partDecada10 VALUES IN (2010, 2011, 2012, 2013, 2014, 20

15, 2016,  11. 2017, 2018, 2019)  12. );  

Por hash: MySQL se encarga de distribuir las tuplas automáticamente usando una

operación de módulo. Sólo hay que pasarle una columna o expresión que resulte

en un entero (el hash) y el número de particiones que queramos crear.

view plaincopy to clipboardprint?

1. ALTER TABLE contratos  2. PARTITION BY HASH(YEAR(fechaInicio))  3. PARTITIONS 7;  

Por clave: similar a la partición por hash, pero en este caso no necesitamos

pasarle un entero; MySQL utilizará su propia función de hash para generarlo. Si no

se indica ninguna columna a partir de la que generar el hash, se utiliza la clave

primaria por defecto.

view plaincopy to clipboardprint?

1. ALTER TABLE contratos  2. PARTITION BY KEY()  3. PARTITIONS 7;  

Compuesta: podemos combinar los distintos métodos de particionado y crear

particiones de particiones

Por último, un pequeño ejemplo de cómo afectaría el particionado a una consulta sencilla

como obtener el número total de tuplas que cumplen una condición. Estas son las

estadísticas de la consulta sin particionado (ni índices)

view plaincopy to clipboardprint?

1. EXPLAIN SELECT COUNT(*)  2. FROM contratos  3. WHERE fechaInicio BETWEEN '1950-01-01' AND '1955-12-31'  

select_type

table typekey

rows Extra

SIMPLEcontratos

ALL

239796

Using where

Y este el resultado de añadir las particiones (nótese la palabra clave PARTITIONS para que

nos muestre también la información relativa a las particiones)

view plaincopy to clipboardprint?

1. EXPLAIN PARTITIONS SELECT COUNT(*)  

Page 4: Particiones en MySQL y Oracle

2. FROM contratos  3. WHERE fechaInicio BETWEEN '1950-01-01' AND '1955-12-31'  

select_type

table partitions typekeyrows

Extra

SIMPLEcontratos

partDecada50

ALL

8640Using where

Como véis, el número de tuplas que MySQL tiene que comprobar se ve disminunido en 2

órdenes de magnitud.

Sintaxis para la creación de las tablas

La estructura de la tabla “NonFTP_Access_log” sin particionar corresponde a la definida en la

siguiente consulta SQL CREATE TABLE

CREATE TABLE `NonFTP_Access_log` (  `id` INT(11) NOT NULL AUTO_INCREMENT,  `clientip` VARCHAR(15) NOT NULL,  `user` CHAR(7) NOT NULL,  `datetime` datetime NOT NULL,  `method` VARCHAR(10) NOT NULL,  `protocol` VARCHAR(10) NOT NULL,  `domain` VARCHAR(255) NOT NULL,  `uri` VARCHAR(100) NOT NULL,  `return_code` SMALLINT(5) UNSIGNED NOT NULL,  `size` INT(10) UNSIGNED NOT NULL,  PRIMARY KEY (`id`),  INDEX `domain` (`domain`),  INDEX `datetime` (`datetime`)) ENGINE=MyISAM DEFAULT CHARSET=utf8

Y con particiones, una para cada mes del 2012 a la siguiente

CREATE TABLE `NonFTP_Access_log` (  `id` INT(11) NOT NULL AUTO_INCREMENT,  `clientip` VARCHAR(15) NOT NULL,  `user` CHAR(7) NOT NULL,  `datetime` datetime NOT NULL,  `method` VARCHAR(10) NOT NULL,  `protocol` VARCHAR(10) NOT NULL,  `domain` VARCHAR(255) NOT NULL,  `uri` VARCHAR(100) NOT NULL,  `return_code` SMALLINT(5) UNSIGNED NOT NULL,  `size` INT(10) UNSIGNED NOT NULL,  PRIMARY KEY (`id`, `datetime`),

Page 5: Particiones en MySQL y Oracle

  INDEX `domain` (`domain`),  INDEX `datetime` (`datetime`)) ENGINE=MyISAM DEFAULT CHARSET=utf8partition BY range COLUMNS (datetime)(partition p1 VALUES less than ('2012-02-01 00:00:00') engine = myisam,partition p2 VALUES less than ('2012-03-01 00:00:00') engine = myisam,partition p3 VALUES less than ('2012-04-01 00:00:00') engine = myisam,partition p4 VALUES less than ('2012-05-01 00:00:00') engine = myisam,partition p5 VALUES less than ('2012-06-01 00:00:00') engine = myisam,partition p6 VALUES less than ('2012-07-01 00:00:00') engine = myisam,partition p7 VALUES less than ('2012-08-01 00:00:00') engine = myisam,partition p8 VALUES less than ('2012-09-01 00:00:00') engine = myisam,partition p9 VALUES less than ('2012-10-01 00:00:00') engine = myisam,partition p10 VALUES less than ('2012-11-01 00:00:00') engine = myisam,partition p11 VALUES less than ('2012-12-01 00:00:00') engine = myisam,partition p12 VALUES less than ('2013-01-01 00:00:00') engine = myisam);