我有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的存储引擎,因为一次有多个用户对此表进行多次读取(选择查询)?
请数据库专家帮助我。
谢谢
答案 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;