如何分区这个大型MySQL表?

时间:2014-05-01 14:25:51

标签: mysql sql database-partitioning large-data

我有一个大约有10亿行的表格,如下所示:

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

我运行的所有查询都有一行如下所示:

 WHERE `station` = "ABSUXNNSDIA3"

和一行如下:

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

station字段有大约30,000个唯一值,没有任何查询引用超过1个站点。理想情况下,我想模拟33,333个不同的表格;每站一个(10亿/ 30,000 = 33,333)。

最初我认为我可以通过在HASH index上设置station来完成此操作,但显然这只适用于MEMORY个表。然后我想我PARTITION BY KEY (station) PARTITIONS 33333,但似乎分区太多了。

在这种情况下我该怎么办?我无法真正进行实验,因为表格太大,任何修改都需要很长时间。

没有主/从或复制或群集或任何类似的东西。

1 个答案:

答案 0 :(得分:0)

每个电台不一定需要一个分区。 HASH或KEY分区的关键是您定义了固定数量的分区,并将多个值映射到该分区。

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

我根据习惯选择分区数的素数,因为如果数据遵循模式(如奇数值),它有助于更​​均匀地在分区上分布数据。

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());

当我使用EXPLAIN PARTITIONS运行查询时,它告诉我必须读取哪个分区。

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 |
+----+-------------+-----------+------------+------+-----------------+---------+---------+-------+------+-------------+

在这种情况下,我们可以看到,当我引用电台' tuv'时,只读取了分区21。

请注意,分区不是灵丹妙药。如果在定义为分区键的同一列中搜索常量值(不是变量或连接条件等),它只会减少查询的工作量。< / p>

我刚刚插入的行应该大致均匀分布,但完全均匀分布。并且不保证每个分区的值为station

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。:station上的表格索引是多余的,因为它已经是主键最左边的列。