2014-05-01 4 views
0

J'ai une table avec environ 1 milliard de lignes qui ressemble à ceci:Comment partitionner cette grande table MySQL?

CREATE TABLE `ghcnddata` (
`date` date NOT NULL , 
`TMIN` float(6,2) NULL DEFAULT NULL , 
`TMAX` float(6,2) NULL DEFAULT NULL , 
`PRCP` float(6,2) NULL DEFAULT NULL , 
`SNOW` float(6,2) NULL DEFAULT NULL , 
`SNWD` float(6,2) NULL DEFAULT NULL , 
`station` varchar(30), 
PRIMARY KEY (`station`, `date`), 
INDEX `date` (`date`) USING BTREE , 
INDEX `station` (`station`) USING BTREE 
) ENGINE=InnoDB 

Toutes les requêtes I Run ont une ligne qui ressemble à ceci:

WHERE `station` = "ABSUXNNSDIA3" 

et une ligne qui ressemble comme ceci:

AND `date` BETWEEN "1990-01-01" AND "2010-01-01" 

Il y a environ 30 000 valeurs uniques pour le champ station, et aucune requête se réfèrent à plus de 1 poste. Idéalement, j'aimerais simuler 33 333 tables différentes; un par station (1 milliard/30 000 = 33 333).

Initialement, je pensais que je pouvais accomplir cela en définissant un HASH index sur station, mais apparemment, c'est seulement pour MEMORY tables. Ensuite, je pensais que je PARTITION BY KEY (station) PARTITIONS 33333, mais il semble que ce soit beaucoup trop de partitions.

Que dois-je faire dans ce scénario? Je ne peux pas vraiment expérimenter parce que la table est si grande que les modifications prennent beaucoup de temps.

Il n'y a pas de maître/esclave ou de réplication ou de clustering ou quoi que ce soit de fantaisie.

+0

Etes-vous sûr que le partitionnement est une bonne idée? –

+0

Eh bien, non - mais si ce n'est pas une bonne situation pour le partitionnement, c'est quoi? Les requêtes sur cette table prennent une éternité, mais si je copie l'une des 33333 stations dans sa propre table, et interroge cela - c'est rapide. Est-ce qu'il n'y a aucun moyen de simuler cela sans réellement faire 33333 tables? –

+0

La raison pour laquelle il est rapide avec l'une table ne s'adapte pas à autant de tables - vous aurez seulement 1/33333 de la clé et du cache de la piscine par opposition à la table unique. –

Répondre

0

Vous n'avez pas nécessairement besoin d'une partition par station. Le point de partitionnement HASH ou KEY est que vous définissez un nombre fixe de partitions et que plusieurs valeurs sont mappées dans cette partition.

mysql> alter table ghcnddata partition by key(station) partitions 31; 

Je choisis un nombre premier pour le nombre de partitions par habitude, parce qu'elle aide à distribuer des données sur les partitions plus uniformément si les données suivent un modèle (comme seules valeurs impaires).

mysql> insert into ghcnddata (station, date) values ('abc', now()); 
mysql> insert into ghcnddata (station, date) values ('def', now()); 
mysql> insert into ghcnddata (station, date) values ('ghi', now()); 
mysql> insert into ghcnddata (station, date) values ('jkl', now()); 
mysql> insert into ghcnddata (station, date) values ('mno', now()); 
mysql> insert into ghcnddata (station, date) values ('qrs', now()); 
mysql> insert into ghcnddata (station, date) values ('tuv', now()); 
mysql> insert into ghcnddata (station, date) values ('wxyz', now()); 

Quand je lance une requête avec EXPLAIN PARTITIONS il me dit quelle partition (s) il doit lire.

mysql> explain partitions select * from ghcnddata where station='tuv'; 
+----+-------------+-----------+------------+------+-----------------+---------+---------+-------+------+-------------+ 
| id | select_type | table  | partitions | type | possible_keys | key  | key_len | ref | rows | Extra  | 
+----+-------------+-----------+------------+------+-----------------+---------+---------+-------+------+-------------+ 
| 1 | SIMPLE  | ghcnddata | p21  | ref | PRIMARY,station | PRIMARY | 122  | const | 1 | Using where | 
+----+-------------+-----------+------------+------+-----------------+---------+---------+-------+------+-------------+ 

On peut voir dans ce cas que seule la partition 21 a été lue lorsque je référence la station 'tuv'.

Notez que le partitionnement n'est pas une panacée. Il est utile de réduire le travail de la requête si vous recherchez une valeur de constante (pas une variable ou une condition de jointure, etc.) dans la même colonne que vous avez définie comme clé de partitionnement.

Les lignes que je viens d'insérer doivent être réparties à peu près uniformément, mais pas uniformément uniformément répartie. Et il n'y a aucune garantie que c'est une valeur station par partition.

mysql> select table_name, partition_name, table_rows 
    from information_schema.partitions where table_name='ghcnddata'; 

+------------+----------------+------------+ 
| table_name | partition_name | table_rows | 
+------------+----------------+------------+ 
| ghcnddata | p0    |   1 | 
| ghcnddata | p1    |   2 | 
| ghcnddata | p2    |   0 | 
| ghcnddata | p3    |   0 | 
| ghcnddata | p4    |   0 | 
| ghcnddata | p5    |   0 | 
| ghcnddata | p6    |   0 | 
| ghcnddata | p7    |   0 | 
| ghcnddata | p8    |   0 | 
| ghcnddata | p9    |   0 | 
| ghcnddata | p10   |   0 | 
| ghcnddata | p11   |   0 | 
| ghcnddata | p12   |   0 | 
| ghcnddata | p13   |   0 | 
| ghcnddata | p14   |   0 | 
| ghcnddata | p15   |   0 | 
| ghcnddata | p16   |   0 | 
| ghcnddata | p17   |   0 | 
| ghcnddata | p18   |   0 | 
| ghcnddata | p19   |   0 | 
| ghcnddata | p20   |   0 | 
| ghcnddata | p21   |   2 | 
| ghcnddata | p22   |   1 | 
| ghcnddata | p23   |   1 | 
| ghcnddata | p24   |   1 | 
| ghcnddata | p25   |   0 | 
| ghcnddata | p26   |   0 | 
| ghcnddata | p27   |   0 | 
| ghcnddata | p28   |   0 | 
| ghcnddata | p29   |   0 | 
| ghcnddata | p30   |   0 | 
+------------+----------------+------------+ 

P.S .: index de votre tableau station est redondant, parce que c'est la colonne de gauche de votre clé primaire déjà.

Questions connexes