优化 SQLite 内部连接查询 - Android

Optimizing SQLite Inner Join Query - Android

我正在使用 GTFS 并试图找到一种方法来加速我的内部连接。 tables "Trips" 和 "StopTimes" 有一个共同的列 "TripID" 而 tables "StopTimes" 和 "Stops" 有一个共同的列"StopID"。内部连接检索与某个 Trip 对应的所有 Stops,但它需要大约 20 秒。此外,"StopTimes" table 包含 900 万行,而其他行则包含几千行。以下代码是我的查询。

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);";

我遵循了在这里找到的一些建议,但仍然无法加快我的查询速度,欢迎任何反馈。

更新 我更改了 table 的创建方式,并为 INNER JOIN 查询中涉及的两个索引添加了索引,现在 JOINS 是即时的。

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)");

我看到您正在使用 SQLite's FTS3 extension,它旨在提高 full-text 搜索的性能。我怀疑这实际上对您发出的查询类型不利(以及通常 运行 针对 GTFS 数据的查询类型)。

我建议您首先创建一个传统的关系数据库,在适当的列上使用索引,然后测试查询的性能。在这种类型的应用程序中使用时,SQLite 肯定能够提供良好的性能,因此我认为您会感到惊喜。一旦您使用传统技术证明了成功,您可以研究其他方法来使查询 运行 更快,如有必要。

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