分区MySQL表后创建索引?

时间:2012-07-27 06:58:26

标签: mysql indexing partitioning

我有mysql表Stop_Times,有2000万条记录。

我正在为此表使用MyISAM存储引擎。

我的表结构是

| agency_id           | varchar(50) | NO   |     | NULL    |       |
| trip_id             | varchar(50) | NO   | PRI | NULL    |       |
| arrival_time        | time        | NO   |     | NULL    |       |
| departure_time      | time        | NO   |     | NULL    |       |
| stop_id             | varchar(50) | NO   | PRI | NULL    |       |
| stop_sequence       | int(11)     | NO   | PRI | NULL    |       |
| route_id            | varchar(50) | NO   |     | NULL    |       |
| route_type          | int(5)      | NO   |     | NULL    |       |
+---------------------+-------------+------+-----+--------

show create table Stop_Times 的输出是 -

CREATE TABLE `Stop_Times` (
 `agency_id` varchar(50) NOT NULL,
 `trip_id` varchar(50) NOT NULL,
 `arrival_time` time NOT NULL,
 `departure_time` time NOT NULL,
 `stop_id` varchar(50) NOT NULL,
 `stop_sequence` int(11) NOT NULL,
 `route_id` varchar(50) NOT NULL,
 `route_type` int(5) NOT NULL,
 UNIQUE KEY `idx_Stop_Times` (`agency_id`,`trip_id`,`stop_sequence`,`stop_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8
/*!50100 PARTITION BY KEY (stop_id)
PARTITIONS 250 */

我有一个查询

select distinct trip_id, stop_sequence from Stop_Times where agency_id = ? and stop_id = ?

在对表格进行分区之前,此查询花费的时间超过4-5分钟。

但是现在我已经将表格分区为 stop_id 按键分区(stop_id)

现在这个查询需要2-3秒才能执行。

我有另一个查询,然后是上面的查询 -

select distinct(stop_id) from Stop_Times where agency_id = ? and trip_id = ? and stop_sequence > ? 

上述查询的解释输出为 -

1   SIMPLE  Stop_Times  range   idx_Stop_Times  idx_Stop_Times  308 NULL    250 Using where; Using index; Using temporary

此查询需要花费更多时间90 - 150秒。

所以我的问题是我是否需要在trip_id和stop_sequence上创建索引? 这会加快查询性能吗?

我是否需要从InnoDB 更改MyISAM的存储引擎,因为一次有多个用户对此表进行多次读取(选择查询)?

请数据库专家帮助我。

谢谢

2 个答案:

答案 0 :(得分:1)

(agency_id, trip_id, stop_sequence, stop_id)上创建覆盖索引。请注意,索引中列的顺序很重要。使用不同的订单可能效率较低。

答案 1 :(得分:1)

也许你想考虑分片这个数据集。

我维护了一个名为Shard-Query的工具,它可以并行查询所有分片 。您有一个自然的分片键(stop_id),您当前正在使用它进行KEY分区。使用Shard-Query,您可以将此相同列与HASH分区一起使用,这样您就可以获得功能等效。

使用Shard-Query,您将创建250个数据库,每个数据库都具有相同的表副本。这相当于您的250个分区。

分区消除
执行第一个查询时,Shard-Query只将查询发送到包含给定stop_id的分区。这与MySQL分区修剪相同。

大规模并行处理(MPP)
对于第二个查询,Shard-Query将根据您运行的gearman(消息队列)worker的数量扫描并行的分区。如果你有一个16核心机器,你可以在分区上获得16度的并行性,而不是MySQL对所有分区的单线程扫描。

只要您的服务器具有处理并行性的资源,您就会看到并行扫描会大幅提高速度。如果没有,您可以将数据拆分为N个服务器(这是MPP中的大量数据),并且在添加节点时将获得线性扩展。请记住,添加或删除分片需要在使用HASH分区时重新加载所有数据,因此这种情况应该不常见。

一个警告:
Shard-Query支持COUNT(DISTINCT)但不支持SELECT DISTINCT ...
您只需重写查询即可使用GROUP BY:

查询#1

select trip_id, stop_sequence from Stop_Times where agency_id = ? and stop_id = ? group by trip_id, stop_sequence;

查询#2

select stop_id from Stop_Times where agency_id = ? and trip_id = ? and stop_sequence > ? group by stop_id;