为androidsqlite优化SQL语句
我正在开发一个应用程序,跟踪用户的当前位置并将其存储到SQLite数据库中。一切正常,但现在我在数据库中查询超过1000条记录的曲目时遇到了问题,这几乎需要1.5分钟。在我的桌面上只需要1秒 我知道这是一个包含许多子选择的查询,但我无法通过另一种方式得到正确的结果。我认为这属于聚合函数,如avg()和sum() 我的问题是:为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
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。在我的桌面上它可以工作。