2012-07-27 141 views
1

我有2千万条记录的mysql表Stop_Times。分区MySQL表后创建索引?

我对此表使用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 |  | 
+---------------------+-------------+------+-----+-------- 

显示创建表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像以key(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中更改存储引擎,因为此表有多次来自多个用户的读取(选择查询)?

请数据库大师帮帮我。

谢谢

回答

1

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

+0

谢谢马克的回复。我将按给定的顺序创建一个索引。但是,由于表上的读取次数,我是否需要更改存储引擎? – Deepu 2012-07-27 07:11:44

+0

我不认为你需要改变引擎。在添加索引后您获得了哪些性能? – 2012-07-27 07:24:36

+0

嗨马克我已经创建了索引,第二个查询需要约30秒。我认为执行查询也太多了。 – Deepu 2012-07-27 08:02:30

1

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

我维护一个名为Shard-Query的工具,它可以并行查询的所有分片。您有一个自然分片键(stop_id),您正在使用它来进行KEY分区。使用Shard-Query,您可以使用HASH分区的相同列,以便您获得功能等同性。

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

分区消除
当你执行的第一个查询,碎片查询将查询发送只包含给定stop_id分区。这与MySQL分区修剪相同。

大规模并行处理(MPP)
对于第二个查询,碎片-查询将扫描分区并联,基于Gearman的(消息队列),其在运行工人的数量。如果你有一台16核心机器,你可以在分区上获得16度的并行度,而不是MySQL对所有分区的单线程扫描。

只要您的服务器具有处理并行性的资源,您将会看到平行扫描带来的巨大速度增加。如果没有,您可以将数据拆分为N个服务器(这是MPP中的大量数据),您可以在添加节点时获得线性缩放比例。请记住,如果使用HASH分区,添加或删除碎片需要重新加载所有数据,所以这应该很少。

警告:
碎片查询支持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; 
+0

感谢greenlion。有'分组'的不同方式。我将尝试这一点。 – Deepu 2012-08-03 07:29:24