1

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

我正在为这个表使用 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更改存储引擎,因为一次有多个用户对该表进行多次读取(选择查询)?

请数据库大师帮助我。

谢谢你

4

2 回答 2

1

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

于 2012-07-27T07:03:29.907 回答
1

也许您想考虑对这个数据集进行分片。

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

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

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

大规模并行处理 (MPP)
对于第二个查询,Shard-Query 将根据您运行的 gearman(消息队列)工作人员的数量并行扫描分区。如果你有一台 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;
于 2012-07-31T20:32:23.793 回答