我正在尝试处理GTFS数据库,具体来说是RATP为巴黎及其周边提供的数据库。
数据集非常庞大。stop_times表有1400万行。
以下是表模式:https://github.com/mauryquijada/gtfs-mysql/blob/master/gtfs-sql.sql 我正在尝试找到在特定位置获取可用路线的最有效方法。就我理解的GTFS规范而言,这里是我的数据从(纬度/经度)到路线的表格和链接:
我将我想要的内容编译成了三个步骤(实际上是我们在上面四个表格之间的三个链接),为了清晰起见,发布在这个gist下:https://gist.github.com/BenoitDuffez/4eba85e3598ebe6ece5f
以下是我创建此脚本的方法。
我能够在不到一秒钟的时间内快速找到所有步行距离内(比如200米)的站点。我使用:
数据集非常庞大。stop_times表有1400万行。
以下是表模式:https://github.com/mauryquijada/gtfs-mysql/blob/master/gtfs-sql.sql 我正在尝试找到在特定位置获取可用路线的最有效方法。就我理解的GTFS规范而言,这里是我的数据从(纬度/经度)到路线的表格和链接:
stops | stop_times | trips | routes
-----------+----------------+------------+--------------
lat | stop_id | trip_id | route_id
lon | trip_id | route_id |
stop_id | | |
我将我想要的内容编译成了三个步骤(实际上是我们在上面四个表格之间的三个链接),为了清晰起见,发布在这个gist下:https://gist.github.com/BenoitDuffez/4eba85e3598ebe6ece5f
以下是我创建此脚本的方法。
我能够在不到一秒钟的时间内快速找到所有步行距离内(比如200米)的站点。我使用:
$ . mysql.ini && time mysql -h $host -N -B -u $user -p${pass} $name -e "SELECT stop_id, (6371000*acos(cos(radians(48.824699))*cos(radians(s.stop_lat))*cos(radians(2.3243)-radians(s.stop_lon))+sin(radians(48.824699))*sin(radians(s.stop_lat)))) AS distance
FROM stops s
GROUP BY s.stop_id
HAVING distance < 200
ORDER BY distance ASC" | awk '{print $1}'
3705271
4472979
4036891
4036566
3908953
3908755
3900765
3900693
3900607
4473141
3705272
4472978
4036892
4036472
4035057
3908952
3705288
3908814
3900832
3900672
3900752
3781623
3781622
real 0m0.797s
user 0m0.000s
sys 0m0.000s
然后,获取所有今天之后的停靠时间(使用 stop_times.departure_time > '``date +%T``'
)需要花费很长时间:
"SELECT trip_id
FROM stop_times
WHERE
stop_id IN ($stops) AND departure_time >= '$now'
GROUP BY trip_id"
在第一步中,$stops
包含从获取到的站点列表。以下是一个例子:
$ . mysql.ini && time mysql -h $host -N -B -u $user -p${pass} $name -e "SELECT stop_id, (6371000*acos(cos(radians(
FROM stops s
GROUP BY s.stop_id
HAVING distance < 200
ORDER BY distance ASC" | awk '{print $1}'
3705271
4472979
4036891
4036566
3908953
...
9916360850964321
9916360920964320
9916360920964321
real 1m21.399s
user 0m0.000s
sys 0m0.000s
这个结果有超过2000行。
我最后的步骤是选择所有与这些trip_id
相匹配的路线。这非常简单,并且相当快速:
$ . mysql.ini && time mysql -h $host -u $user -p${pass} $name -e "SELECT r.id, r.route_long_name FROM trips t, routes r WHERE t.trip_id IN (`cat trip_ids | tr '\n' '#' | sed -e 's/##$//' -e 's/#/,/g'`) AND r.route_id = t.route_id GROUP BY t.route_id"
+------+-------------------------------------------------------------------------+
| id | route_long_name |
+------+-------------------------------------------------------------------------+
| 290 | (PLACE DE CLICHY <-> CHATILLON METRO) - Aller |
| 291 | (PLACE DE CLICHY <-> CHATILLON METRO) - Retour |
| 404 | (PORTE D'ORLEANS-METRO <-> ECOLE VETERINAIRE DE MAISON-ALFORT) - Aller |
| 405 | (PORTE D'ORLEANS-METRO <-> ECOLE VETERINAIRE DE MAISON-ALFORT) - Retour |
| 453 | (PORTE D'ORLEANS-METRO <-> LYCEE POLYVALENT) - Retour |
| 457 | (PORTE D'ORLEANS-METRO <-> LYCEE POLYVALENT) - Retour |
| 479 | (PORTE D'ORLEANS-METRO <-> VELIZY 2) - Retour |
| 810 | (PLACE DE LA LIBERATION <-> GARE MONTPARNASSE) - Aller |
| 989 | (PORTE D'ORLEANS-METRO) - Retour |
| 1034 | (PLACE DE LA LIBERATION <-> HOTEL DE VILLE DE PARIS_4E__AR) - Aller |
+------+-------------------------------------------------------------------------+
real 0m1.070s
user 0m0.000s
sys 0m0.000s
这里有一个名为trip_ids
的文件,其中包含了2k个trip ID。
如何更快地获得这个结果?除了我已经采取的stops>stop_times>trips>routes
路径之外,是否有更好的方法来爬取数据?
在这里,实际上只需要进行一个查询:“这个位置200米内有哪些路线可用?”总时间大约为30秒。太慢了...
LEFT JOIN
,但它花费了很长时间(实际上我不知道,我用Ctrl-C
中断了查询)。您的查询只花费了53秒,比我所有的查询加起来都要好得多。添加索引花费了一些时间,现在已经过去几分钟了,但它们还没有被创建。请继续关注! - Benoit Duffez18:30:00
的出发时间进行测试,我在36秒内得到了我们在我的问题中看到的结果。 - Benoit Duffez