Оптимизировать оператор SQL для Android SQLite - PullRequest
0 голосов
/ 23 июля 2010

Я разрабатываю приложение, которое отслеживает текущее положение пользователя и сохраняет его в базе данных 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 = ?

Уже 2 часа я ищу решение и не знаю, что я 'Я делаю неправильно.Может быть, мне нужно сделать перерыв.

РЕДАКТИРОВАТЬ:

Вот мои заявления создания:

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

Ответы [ 3 ]

3 голосов
/ 23 июля 2010

Не упрощать, но я думаю, что вы могли бы сэкономить массу времени на ваших запросах, просто проиндексировав поля, которые вы сканируете во время запроса.

Индексируя поля, вы уменьшите все сканирование таблицы, что замедляет запросы по мере роста количества записей.

Недостатком индексов является потребность в пространстве, но по моему опыту на Android, это редко фактор.

2 голосов
/ 22 августа 2010

Это сделает работу:

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

Добавьте поля по мере необходимости.

1 голос
/ 23 июля 2010

Нечто подобное может приблизить вас. Обратите внимание, что я включил параметр несколько раз в запрос:

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 = ?
...