为androidsqlite优化SQL语句

为androidsqlite优化SQL语句,sql,android,sqlite,query-optimization,Sql,Android,Sqlite,Query Optimization,我正在开发一个应用程序,跟踪用户的当前位置并将其存储到SQLite数据库中。一切正常,但现在我在数据库中查询超过1000条记录的曲目时遇到了问题,这几乎需要1.5分钟。在我的桌面上只需要1秒 我知道这是一个包含许多子选择的查询,但我无法通过另一种方式得到正确的结果。我认为这属于聚合函数,如avg()和sum() 我的问题是: Cursor c = readableDB .rawQuery( "SELECT DISTINCT t._id , title , strf

我正在开发一个应用程序,跟踪用户的当前位置并将其存储到SQLite数据库中。一切正常,但现在我在数据库中查询超过1000条记录的曲目时遇到了问题,这几乎需要1.5分钟。在我的桌面上只需要1秒

我知道这是一个包含许多子选择的查询,但我无法通过另一种方式得到正确的结果。我认为这属于聚合函数,如avg()和sum()

我的问题是:

Cursor c = readableDB
    .rawQuery(
            "SELECT DISTINCT t._id , title , strftime('%Y-%m-%d' , starttime , 'unixepoch' , 'localtime') as date , description, "
            + "round((SELECT sum(distToPrev)/1000 FROM positions p WHERE p.trackid=t._id) , 2) as distance , " 
            + "(SELECT count(latitude) FROM positions p WHERE p.trackid=t._id) as waypoints, "
            + "(SELECT (avg(speed)*3.6) FROM positions p WHERE p.trackid=t._id) as avgspeed, "
            + "(SELECT (max(speed)*3.6) FROM positions p WHERE p.trackid=t._id) as maxspeed, "
            + "(SELECT sum(altitudeUP) FROM positions p WHERE p.trackid=t._id) as climb , "
            + "(SELECT avg(heartbeat) FROM heartbeats h WHERE h.trackid=t._id) as avgheartbeat , "
            + "(SELECT max(heartbeat) FROM heartbeats h WHERE h.trackid=t._id) as maxheartbeat , "
            + "(SELECT avg(cadence) FROM heartbeats h WHERE h.trackid=t._id) as avgcadence "
            + "FROM tracks t LEFT JOIN heartbeats h ON t._id = h.trackid WHERE t._id = ?",
            new String[]{String.valueOf(trackId)}); 
    c.moveToFirst();
如何优化此查询?我已经这样试过了,但是结果是错误的,花费了同样的时间

SELECT t._id , title , strftime('%Y-%m-%d' , starttime , 'unixepoch' , 'localtime') as date , description,
sum(distToPrev)/1000 as distance ,
count(latitude) as waypoints, 
(avg(speed)*3.6) as avgspeed, 
(max(speed)*3.6) as maxspeed, 
sum(altitudeUP) as climb , 
avg(heartbeat)  as avgheartbeat ,
max(heartbeat)  as maxheartbeat ,
avg(cadence) as avgcadence 
FROM tracks t 
LEFT JOIN heartbeats h ON t._id = h.trackid 
INNER JOIN positions p ON t._id = p.trackid 
     WHERE t._id = ?
两个小时以来,我一直在寻找解决方案,我不知道自己做错了什么。也许我得休息一下

编辑:

下面是我的create语句:

CREATE TABLE heartbeats(_id INTEGER PRIMARY KEY AUTOINCREMENT, trackid INTEGER NOT NULL, heartbeat INTEGER NOT NULL, cadence INTEGER, timestamp TIMESTAMP);


CREATE TABLE positions(_id INTEGER PRIMARY KEY AUTOINCREMENT, trackid INTEGER NOT NULL, longitude REAL NOT NULL, latitude REAL NOT NULL, altitude REAL, altitudeUP REAL, speed REAL, accuracy REAL, distToPrev REAL, timestamp TIMESTAMP);


CREATE TABLE tracks(_id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT NOT NULL, description TEXT, starttime DATETIME NOT NULL, endtime DATETIME);

像这样的事情可能会让你接近。请注意,我在查询中多次包含该参数:

SELECT
    T._id,
    T.title,
    STRFTIME('%Y-%m-%d' , T.starttime , 'unixepoch' , 'localtime') as date,
    T.description,
    P_SQ.distance,
    P_SQ.waypoints,
    P_SQ.avg_speed,
    P_SQ.max_speed,
    P_SQ.climb
FROM
    Tracks T
LEFT OUTER JOIN
(
    SELECT
        P.trackid,
        SUM(P.distToPrev) AS distance,
        COUNT(P.latitude) AS waypoints,
        AVG(P.speed) * 3.6 AS avg_speed,
        MAX(P.speed) * 3.6 AS max_speed,
        SUM(altitudeUp) AS climb
    FROM
        Positions P
    WHERE
        P.trackid = ?
    GROUP BY
        P.trackid
) P_SQ ON P_SQ.trackid = T._id
LEFT OUTER JOIN
(
    SELECT
        H.trackid,
        AVG(heartbeat) AS avg_heartbeat,
        MAX(heartbeat) AS max_heartbeat,
        AVG(cadence) AS avg_cadence
    FROM
        Heartbeats
    WHERE
        H.trackid = ?
    GROUP BY
        H.trackid
) H_SQ ON H_SQ.trackid = T._id
WHERE
    T._id = ?

像这样的事情可能会让你接近。请注意,我在查询中多次包含该参数:

SELECT
    T._id,
    T.title,
    STRFTIME('%Y-%m-%d' , T.starttime , 'unixepoch' , 'localtime') as date,
    T.description,
    P_SQ.distance,
    P_SQ.waypoints,
    P_SQ.avg_speed,
    P_SQ.max_speed,
    P_SQ.climb
FROM
    Tracks T
LEFT OUTER JOIN
(
    SELECT
        P.trackid,
        SUM(P.distToPrev) AS distance,
        COUNT(P.latitude) AS waypoints,
        AVG(P.speed) * 3.6 AS avg_speed,
        MAX(P.speed) * 3.6 AS max_speed,
        SUM(altitudeUp) AS climb
    FROM
        Positions P
    WHERE
        P.trackid = ?
    GROUP BY
        P.trackid
) P_SQ ON P_SQ.trackid = T._id
LEFT OUTER JOIN
(
    SELECT
        H.trackid,
        AVG(heartbeat) AS avg_heartbeat,
        MAX(heartbeat) AS max_heartbeat,
        AVG(cadence) AS avg_cadence
    FROM
        Heartbeats
    WHERE
        H.trackid = ?
    GROUP BY
        H.trackid
) H_SQ ON H_SQ.trackid = T._id
WHERE
    T._id = ?

这并不是说过于简单,但我认为只需对查询期间扫描的字段进行索引,就可以节省大量查询时间

通过对字段进行索引,您将减少所有的表扫描,这些扫描会随着记录数量的增加而减慢查询速度


索引的缺点是空间需求,但根据我在Android上的经验,这很少是一个因素

不要过于简单化,但我认为只需对查询期间扫描的字段进行索引,就可以节省大量查询时间

通过对字段进行索引,您将减少所有的表扫描,这些扫描会随着记录数量的增加而减慢查询速度

索引的缺点是空间需求,但根据我在Android上的经验,这很少是一个因素

这将完成工作:

SELECT tid, date, waypoints, avg(heartbeat) AS avgheartbeat 
FROM (SELECT t._id AS tid, strftime('%Y-%m-%d' , starttime , 'unixepoch' , 'localtime') AS date, count(latitude) AS waypoints
         FROM tracks t LEFT JOIN positions p ON t._id = p.trackid  
         WHERE t._id = ?
         GROUP BY t._id , strftime('%Y-%m-%d' , starttime , 'unixepoch' , 'localtime'))
    LEFT JOIN heartbeats h ON tid = h.trackid
GROUP BY tid, date, waypoints
根据需要添加字段。

这将完成以下工作:

SELECT tid, date, waypoints, avg(heartbeat) AS avgheartbeat 
FROM (SELECT t._id AS tid, strftime('%Y-%m-%d' , starttime , 'unixepoch' , 'localtime') AS date, count(latitude) AS waypoints
         FROM tracks t LEFT JOIN positions p ON t._id = p.trackid  
         WHERE t._id = ?
         GROUP BY t._id , strftime('%Y-%m-%d' , starttime , 'unixepoch' , 'localtime'))
    LEFT JOIN heartbeats h ON tid = h.trackid
GROUP BY tid, date, waypoints

根据需要添加字段。

您指定了表别名,但除了第一个SELECT列之外,无法使用它们。我们不知道其余列来自哪些表,因此无法提供任何有价值的建议…请发布您的表架构,并包括您也已添加的索引。添加了我的create语句。表上没有索引。您应该在查询中使用的所有数值列上添加索引,特别是对于联接和where子句使用的列。这将大大提高性能。您可以指定表别名,但除了第一个SELECT列之外,无法使用它们。我们不知道其余列来自哪些表,因此无法提供任何有价值的建议…请发布您的表架构,并包括您也已添加的索引。添加了我的create语句。表上没有索引。您应该在查询中使用的所有数值列上添加索引,特别是对于联接和where子句使用的列。这将提高很多。看起来很好,但现在我得到了一个android.database.sqlite.SQLiteException:没有这样的列:H_SQ.trackid。在我的桌面上它可以工作。看起来很好,但现在我得到了一个android.database.sqlite.SQLiteException:没有这样的列:H_SQ.trackid。在我的桌面上它可以工作。