使此SQLite查询更高效

使此SQLite查询更高效,sqlite,android-sqlite,Sqlite,Android Sqlite,我开发了一个Android应用程序,允许用户以各种方式查看电视指南。其中一个视图是“现在/下一个”视图,它基本上是一个带有分隔符(显示频道名称)的列表,每个分隔符后跟当前/下一个电视节目的详细信息 我遇到的问题是,测试我自己的67个频道阵容需要20-30秒才能生成视图(移动应用程序的速度非常慢),我知道我的一些用户拥有约200多个频道 我用于获取1个通道的“现在/下一个”详细信息的SQL查询如下所示 SELECT b.oid AS _id, b.channel_oid,

我开发了一个Android应用程序,允许用户以各种方式查看电视指南。其中一个视图是“现在/下一个”视图,它基本上是一个带有分隔符(显示频道名称)的列表,每个分隔符后跟当前/下一个电视节目的详细信息

我遇到的问题是,测试我自己的67个频道阵容需要20-30秒才能生成视图(移动应用程序的速度非常慢),我知道我的一些用户拥有约200多个频道

我用于获取1个通道的“现在/下一个”详细信息的SQL查询如下所示

SELECT
    b.oid AS _id,
    b.channel_oid,
    b.title,
    b.start_time,
    b.end_time
FROM epg_event b,
    (
        SELECT
            MIN(a.start_time) AS start_time,
            a.channel_oid,
            a.end_time
        FROM epg_event a
        WHERE a.start_time  > datetime('now')
          AND a.channel_oid = 10029
        GROUP BY a.channel_oid
        UNION
        SELECT
            MIN(a.start_time) AS start_time,
            a.channel_oid,
            a.end_time
        FROM epg_event a
        WHERE a.start_time <= datetime('now')
          AND a.end_time    > datetime('now')
          AND a.channel_oid = 10029
        GROUP BY a.channel_oid
    ) c
WHERE c.start_time  = b.start_time
  AND c.channel_oid = b.channel_oid
ORDER BY b.start_time
显示的查询将返回

_id, channel_oid, title, start_time, end_time
10467376, 10029, Ripper Street, 2013-01-20 21:00:00, 2013-01-20 22:00:00
10467377, 10029, BBC News; Regional News and Weather, 2013-01-20 22:00:00, 2013-01-20 22:25:00

据我所知,您的查询的这一部分应该得到任何仍在播放或尚未开始的节目:

    SELECT
        MIN(a.start_time) AS start_time,
        a.channel_oid,
        a.end_time
    FROM epg_event a
    WHERE a.start_time  > datetime('now')
      AND a.channel_oid = 10029
    GROUP BY a.channel_oid
    UNION
    SELECT
        MIN(a.start_time) AS start_time,
        a.channel_oid,
        a.end_time
    FROM epg_event a
    WHERE a.start_time <= datetime('now')
      AND a.end_time    > datetime('now')
      AND a.channel_oid = 10029
    GROUP BY a.channel_oid
现在,您可以按已知的频道ID进行过滤,但仍按它进行分组-为什么?它应该简化为

    SELECT
        MIN(a.start_time) AS start_time,
        a.channel_oid,
        a.end_time
    FROM epg_event a
    WHERE a.end_time > datetime('now')
      AND a.channel_oid = 10029
据我所知,您最好将
datetime('now')
替换为
CURRENT\u TIMESTAMP
。这将生成最终SQL,如下所示:

SELECT
    b.oid AS _id,
    b.channel_oid,
    b.title,
    b.start_time,
    b.end_time
FROM epg_event b,
    (
        SELECT
            MIN(a.start_time) AS start_time,
            a.channel_oid,
            a.end_time
        FROM epg_event a
        WHERE a.end_time > CURRENT_TIMESTAMP
          AND a.channel_oid = 10029
    ) c
WHERE c.start_time  = b.start_time
  AND c.channel_oid = b.channel_oid
ORDER BY b.start_time

要使其快速工作,请确保创建适当的索引。可以为您提供一些如何优化它的想法,但乍一看,您应该至少在
epg\u event
表上有以下复合索引:
(channel\u oid,start\u time)
(channel\u oid,end\u time)

在Jelly Bean之前的Android版本中必须这样做吗?(你的查询没有。)@CL:我已经编辑了这个问题,以显示用于该表的
创建表
。至于它在Jelly Bean之前的版本上的工作,我可以向你保证,我的HTC Desire运行Froyo可以很好地运行查询(尽管速度很慢)。谢谢。我的原始查询实际上得到了一些帮助,因为SQL不是我的强项——我不知道为什么帮助我的人使用GROUP BY。我已经将我的查询压缩为您建议的查询,尽管它只返回1条记录(现在显示的一条),所以我将联合添加到了中,并且它可以工作。然而,真正的解决方法是复合索引——没有它们,压缩查询的速度不会明显加快,但当我添加它们时,它确实起了作用(1-2秒,而不是20-30秒)。再次感谢。很高兴听到这对你有帮助!复合索引确实可以让您的一天变得更美好:-)
    SELECT
        MIN(a.start_time) AS start_time,
        a.channel_oid,
        a.end_time
    FROM epg_event a
    WHERE a.end_time > datetime('now')
      AND a.channel_oid = 10029
SELECT
    b.oid AS _id,
    b.channel_oid,
    b.title,
    b.start_time,
    b.end_time
FROM epg_event b,
    (
        SELECT
            MIN(a.start_time) AS start_time,
            a.channel_oid,
            a.end_time
        FROM epg_event a
        WHERE a.end_time > CURRENT_TIMESTAMP
          AND a.channel_oid = 10029
    ) c
WHERE c.start_time  = b.start_time
  AND c.channel_oid = b.channel_oid
ORDER BY b.start_time