2016-01-07 109 views
0

我正在使用GTFS并试图找出一种方法来加速我的内部联接。表“Trips”和“StopTimes”有一个共同的列“TripID”,表“StopTimes”和“Stop”有一个共同的列“StopID”。内连接检索所有与特定Trip相对应的Stop,但大约需要20秒。此外,“StopTimes”表由900万行组成,而其他组成由几千个。以下代码是我的查询。优化SQLite内部联接查询 - Android

String joinQuery = "SELECT s.stop_id, s.stop_code, s.stop_name " 
+ "FROM Trips as t INNER JOIN StopTimes as st ON  st.trip_id = t.trip_id " 
+ "INNER JOIN Stops as s ON s.stop_id = st.stop_id " 
+ "WHERE t.trip_id = " + TripID + " AND t.shape_id = " + ShapeID 
+ " ORDER BY st.stop_sequence"; 

这是在创建数据库时执行的代码。

String CREATE_TRIPS_TABLE = "CREATE VIRTUAL TABLE " + TABLE_TRIPS + " USING FTS3(" 
      + KEY_T_ROUTE_ID + " INTEGER," 
      + KEY_T_NAME + " TEXT," 
      + KEY_TRIP_ID + " INTEGER," 
      + KEY_DIRECTION_ID + " INTEGER," 
      + KEY_SHAPE_ID + " INTEGER);"; 

    String CREATE_STOPS_TABLE = "CREATE VIRTUAL TABLE " + TABLE_STOPS + " USING FTS3(" 
      + KEY_STOP_ID + " INTEGER," 
      + KEY_STOP_CODE + " TEXT," 
      + KEY_STOP_NAME + " TEXT," 
      + KEY_STOP_LAT + " DOUBLE," 
      + KEY_STOP_LON + " DOUBLE," 
      + KEY_STOP_WHEELCHAIR + " INTEGER);"; 

    String CREATE_STOPTIMES_TABLE = "CREATE VIRTUAL TABLE " + TABLE_STOP_TIMES + " USING FTS3(" 
      + KEY_S_TRIP_ID + " INTEGER," 
      + KEY_S_STOP_ID + " INTEGER," 
      + KEY_ARRIVAL_TIME + " TEXT," 
      + KEY_STOP_SEQUENCE + " INTEGER," 
      + KEY_SHAPE_DIST_TRAVELLED + " DOUBLE);"; 

我跟着我在这里找到的一些建议,我仍然无法加快我的查询,任何反馈表示赞赏。

UPDATE 我改怎么我的表被创建和添加索引的两个参与INNER JOIN查询索引和连接是现在是瞬发。

String CREATE_TRIPS_TABLE = "CREATE TABLE " + TABLE_TRIPS + "(" 
      + KEY_T_ID + " integer PRIMARY KEY AUTOINCREMENT," 
      + KEY_T_ROUTE_ID + " INTEGER," 
      + KEY_T_NAME + " TEXT," 
      + KEY_TRIP_ID + " INTEGER," 
      + KEY_DIRECTION_ID + " INTEGER," 
      + KEY_SHAPE_ID + " INTEGER);"; 

    String CREATE_STOPS_TABLE = "CREATE TABLE " + TABLE_STOPS + "(" 
      + KEY_S_ID + " integer PRIMARY KEY AUTOINCREMENT," 
      + KEY_STOP_ID + " INTEGER," 
      + KEY_STOP_CODE + " TEXT," 
      + KEY_STOP_NAME + " TEXT," 
      + KEY_STOP_LAT + " DOUBLE," 
      + KEY_STOP_LON + " DOUBLE," 
      + KEY_STOP_WHEELCHAIR + " INTEGER);"; 

    String CREATE_STOPTIMES_TABLE = "CREATE TABLE " + TABLE_STOP_TIMES + "(" 
      + KEY_ST_ID + " integer PRIMARY KEY AUTOINCREMENT," 
      + KEY_S_TRIP_ID + " INTEGER," 
      + KEY_S_STOP_ID + " INTEGER," 
      + KEY_ARRIVAL_TIME + " TEXT," 
      + KEY_STOP_SEQUENCE + " INTEGER," 
      + KEY_SHAPE_DIST_TRAVELLED + " DOUBLE);"; 

    db.execSQL(CREATE_ROUTES_TABLE); 
    db.execSQL(CREATE_TRIPS_TABLE); 
    db.execSQL(CREATE_STOPS_TABLE); 
    db.execSQL(CREATE_STOPTIMES_TABLE); 
    db.execSQL("CREATE INDEX T_id ON Trips(trip_id)"); 
    db.execSQL("CREATE INDEX S_t_id ON StopTimes(trip_id)"); 
+0

为什么使用[FTS3扩展](https://www.sqlite.org/fts3.html)而不是构建正常的关系数据库?您是否打算对GTFS数据进行全文搜索? –

+0

@SimonSouth是的,它应该能够更快地搜索数据 – Yenvanio

+1

我确定它会使_full-text_搜索速度更快,但我认为它对您在此处显示的查询类型(以及通常运行的查询类型)反对GTFS数据)。我认为你应该首先尝试以传统的方式定义数据库,在适当的列上使用索引,然后在试图获得扩展之前查看查询的性能。 –

回答

0

我看到您使用的是SQLite's FTS3 extension,它旨在改善全文搜索的性能。我怀疑这实际上是针对你发布的查询(以及通常针对GTFS数据运行的查询)而与你对抗。

我建议您首先创建一个常规的关系数据库,并在相应的列上使用索引,然后根据这些数据测试查询的性能。当在这种类型的应用程序中使用时,SQLite肯定有很好的性能,所以我认为你会感到惊喜。一旦用传统技术演示了成功,您可以查看其他方法,以便在需要时更快地运行查询。

最后,请注意SQLite does not allow indices on virtual tables,我怀疑是您的查询花了这么长时间才能完成的具体原因。

+0

非常感谢所有的信息,创建一个传统的数据库确实加快了这个过程。现在停靠最多的车次不到10秒 – Yenvanio

+0

太棒了!如果您尚未在表格中定义指标,那么创建这些指标也应该有很大的不同。 –

+0

我很困惑,定义索引?我以为我已经在查询中完成了这项工作 – Yenvanio