2010-03-19 3 views
1

Je viens d'essayer de configurer des partitions en fonction de la date, mais il semble que mysql contienne toujours une partition sans données pertinentes. Il utilisera la partition pertinente mais inclura également la plus ancienne pour une raison quelconque. Est-ce que je le fais mal?Partition Mysql: Les partitions en dehors de la plage de dates sont incluses

La version est 5.1.44 (MyISAM)

j'ai ajouté quelques partitions en fonction "jour", qui est de type "date"

ALTER TABLE ptest 
PARTITION BY RANGE(TO_DAYS(day)) 
(
PARTITION p1 VALUES LESS THAN (TO_DAYS('2009-08-01')), 
PARTITION p2 VALUES LESS THAN (TO_DAYS('2009-11-01')), 
PARTITION p3 VALUES LESS THAN (TO_DAYS('2010-02-01')), 
PARTITION p4 VALUES LESS THAN (TO_DAYS('2010-05-01')) 
); 

Après une requête, je trouve que il utilise la "vieille" partition, qui ne devrait contenir aucune donnée pertinente.

mysql> explain partitions select * from ptest where day between '2010-03-11' and '2010-03-12'; 
+----+-------------+------------+------------+-------+---------------+------+---------+------+------+-------------+ 
| id | select_type | table  | partitions | type | possible_keys | key | key_len | ref | rows | Extra  | 
+----+-------------+------------+------------+-------+---------------+------+---------+------+------+-------------+ 
| 1 | SIMPLE  | ptest  | p1,p4  | range | day   | day | 3  | NULL | 79 | Using where | 
+----+-------------+------------+------------+-------+---------------+------+---------+------+------+-------------+ 

Lorsque je sélectionne un seul jour, il fonctionne comme prévu:

mysql> explain partitions select * from ptest where day = '2010-03-11'; 
+----+-------------+------------+------------+------+---------------+------+---------+-------+------+-------+ 
| id | select_type | table  | partitions | type | possible_keys | key | key_len | ref | rows | Extra | 
+----+-------------+------------+------------+------+---------------+------+---------+-------+------+-------+ 
| 1 | SIMPLE  | ptest  | p4   | ref | day   | day | 3  | const | 39 |  | 
+----+-------------+------------+------------+------+---------------+------+---------+-------+------+-------+ 

Répondre

1

Vous avez partitionné sur TO_DAYS (date), cela signifie que la taille de partitionnement surtout se produire que dans des cas simples, sauf si vous appliquez TO_DAYS (date) sur les contraintes.

Vous devrez faire, par ex. select * from ptest où day entre TO_DAYS ('2010-03-11') et TO_DAYS ('2010-03-12') - bien qu'il puisse être dans ce cas des lacunes dans mysql entre.

Partitionner des dates dans mysql est difficile, et il y a beaucoup de lacunes dans l'implémentation du partitionnement, au moins si vous voulez couvrir beaucoup de contraintes de requêtes différentes, nous plaçons généralement un identifiant entier dans les tables pointant vers un calendrier d'un type DATE, comme nous l'avons trouvé MySQL pour gérer le partitionnement sur un simple entier tout à fait fiable par rapport à la séparation des colonnes impliquant une fonction (par exemple TO_DAYS), nous avons

create table datatbl (
    time_id int NOT NULL, 
    .... 
); 

TIME_ID références un calendrier pré-remplie dates pour les 10 prochaines années qui ressemblent à

create table calendar (
    time_id int primary key 
    year int NOT NULL, 
    month int NOT NULL, 
    day int NOT NULL, 
    dayofyear int NOT NULL, 
    quarter int NOT NULL, 
    is_weekend char(1) NOT NULL, 
    db_date DATE not NULL, 
    unique index(year,month,day), 
    unique index(dbdate) 
); 

Les requêtes sont jointes à cette table, donc saisir toutes les données pour un mois nécessite seulement where cal.year = 2010 and cal.month = 1. Ou cela pourrait être fait comme cal.db_date between '2010-01-01' and '2010-01-31'

datatbl est partitionné sur time_id, et les requêtes ci-dessus feront mysql faire l'élagage de partitionnement. time_id est aussi un composite de l'année/mois/date donc le time_id pour 2010-03-03 serait l'entier 20100303, qui ne devrait pas être utilisé pour l'interrogation, c'est simplement une commodité pour les scripts qui créent automatiquement une nouvelle/drop anciennes partitions.

2

Il s'agit en fait du résultat attendu car la partition la plus ancienne contient toujours des valeurs qui n'ont pas été évaluées à une date valide (null). Une solution de contournement pour cela consiste à créer une partition supplémentaire qui ne contient aucune donnée et existe pour toutes les valeurs avant votre date la plus ancienne. Cette partition sera toujours analysée mais a peu d'impact sur les performances car elle est vide.

http://bugs.mysql.com/bug.php?id=49754

Questions connexes