2011-05-23 13 views
10

Quiero particionar una tabla mysql por columna de fecha y hora. Un día, un partition.The crear secuencias de comandos de la tabla es la siguiente:cómo dividir una tabla por columna de fecha y hora?

CREATE TABLE raw_log_2011_4 (
    id bigint(20) NOT NULL AUTO_INCREMENT, 
    logid char(16) NOT NULL, 
    tid char(16) NOT NULL, 
    reporterip char(46) DEFAULT NULL, 
    ftime datetime DEFAULT NULL, 
    KEY id (id) 
) ENGINE=InnoDB AUTO_INCREMENT=286802795 DEFAULT CHARSET=utf8 
PARTITION BY hash (day(ftime)) partitions 31; 

Pero cuando selecciono los datos de algunos day.It no pudo localizar la instrucción select partition.The es así:

explain partitions select * from raw_log_2011_4 where day(ftime) = 30; 

cuando uso otra declaración, podría ubicar la partición, pero no puedo seleccionar datos de algún día.

explain partitions select * from raw_log_2011_4 where ftime = '2011-03-30'; 

¿Hay alguien dime cómo podría seleccionar datos de algún día y hacer uso de la partición. ¡Gracias!

Respuesta

7

Hola Usted está haciendo la partición equivocada en la definición de la tabla de la definición de tabla desea:

CREATE TABLE raw_log_2011_4 (
    id bigint(20) NOT NULL AUTO_INCREMENT, 
    logid char(16) NOT NULL, 
    tid char(16) NOT NULL, 
    reporterip char(46) DEFAULT NULL, 
    ftime datetime DEFAULT NULL, 
    KEY id (id) 
) ENGINE=InnoDB AUTO_INCREMENT=286802795 DEFAULT CHARSET=utf8 
PARTITION BY hash (TO_DAYS(ftime)) partitions 31; 

y su comando de selección sería:

explain partitions 
    select * from raw_log_2011_4 where TO_DAYS(ftime) = '2011-03-30'; 

El comando anterior seleccionaría todos la fecha requerida, como si utilizara el comando TO_DAYS como

mysql> SELECT TO_DAYS(950501); 
     -> 728779 
mysql> SELECT TO_DAYS('2007-10-07'); 
     -> 733321 

¿Por qué utilizar th e TO_DAYS como el optimizador de MySQL reconocerá dos funciones basadas en fechas con fines de poda de reparto 1.TO_DAYS() 2.YEAR()

y esto resolvería el problema ..

+0

'^ 1' ¿y si el número de años en la tabla es desconocido, si' PARTITION BY hash (YEAR (ftime)) 'funcionará? –

1

Hace poco leí una publicación de blog de MySQL relacionada con esto, en http://dev.mysql.com/tech-resources/articles/mysql_55_partitioning.html.

Las versiones anteriores a la 5.1 requerían gimnasia especial para realizar particiones basadas en fechas. El enlace de arriba lo discute y muestra ejemplos.

Las versiones 5.5 y posteriores le permitieron realizar particiones directas utilizando valores no numéricos como fechas y cadenas.

12

Particiones por HASH es una muy mala idea con las columnas de fecha y hora, porque no puede usar partition pruning. A partir de la documentación de MySQL:

La poda se puede utilizar sólo en las columnas enteras de tablas con particiones por HASH o KEY. Por ejemplo, esta consulta en la tabla T4 no puede utilizar la poda porque DOB es una columna FECHA:

SELECT * FROM t4 WHERE dob >= '2001-04-14' AND dob <= '2005-10-15'; 

Sin embargo, si los valores de año tabla almacena en una columna INT, a continuación, una consulta tener DONDE year_col > = 2001 AND year_col < = 2005 puede ser podado.

Así que puede almacenar el valor de TO_DAYS (DATE()) en una columna INTEGER extra para usar la poda.

Otra opción es utilizar la partición GAMA:

CREATE TABLE raw_log_2011_4 (
    id bigint(20) NOT NULL AUTO_INCREMENT, 
    logid char(16) NOT NULL, 
    tid char(16) NOT NULL, 
    reporterip char(46) DEFAULT NULL, 
    ftime datetime DEFAULT NULL, 
    KEY id (id) 
) ENGINE=InnoDB AUTO_INCREMENT=286802795 DEFAULT CHARSET=utf8 
    PARTITION BY RANGE(TO_DAYS(datetime)) (
    PARTITION p20110401 VALUES LESS THAN (TO_DAYS('2011-04-02')), 
    PARTITION p20110402 VALUES LESS THAN (TO_DAYS('2011-04-03')), 
    PARTITION p20110403 VALUES LESS THAN (TO_DAYS('2011-04-04')), 
    PARTITION p20110404 VALUES LESS THAN (TO_DAYS('2011-04-05')), 
    ... 
    PARTITION p20110426 VALUES LESS THAN (TO_DAYS('2011-04-27')), 
    PARTITION p20110427 VALUES LESS THAN (TO_DAYS('2011-04-28')), 
    PARTITION p20110428 VALUES LESS THAN (TO_DAYS('2011-04-29')), 
    PARTITION p20110429 VALUES LESS THAN (TO_DAYS('2011-04-30')), 
    PARTITION future VALUES LESS THAN MAXVALUE 
); 

Ahora la siguiente consulta sólo utilizará p20110403 de partición:

SELECT * FROM raw_log_2011_4 WHERE ftime = '2011-04-03'; 
+0

Estoy aprendiendo acerca de las particiones, ¿cómo es que el uso de 'DATE_FORMAT()' no es necesario en la instrucción 'WHERE'? – enchance

+0

@Steyx - Quizás quiso decir 'DONDE ftime> = '2011-04-03' Y ftime <'2011-04-03' + INTERVALO 1 DÍA '. –

0

No utilice CHAR, utilice VARCHAR. Eso ahorrará mucho espacio, por lo tanto, disminuirá la E/S, por lo tanto, acelerará las consultas.

reporterip: (46) es innecesariamente grande para una dirección IP, incluso IPv6. Ver My blog para mayor discusión, incluyendo cómo reducirlo a 16 bytes.

PARTITION BY RANGE(TO_DAYS(...)) como @Steyx sugerido, pero no tiene más de unas 50 particiones. Cuantas más particiones tenga, más lentas serán las consultas, a pesar de la "poda". HASH particionamiento es esencialmente inútil.

More discussion of partitioning, especially the type you are looking at. Eso incluye el código para un conjunto deslizante de particiones en el tiempo.

Cuestiones relacionadas