【问题标题】:Making this SQLite query more efficient使这个 SQLite 查询更高效
【发布时间】:2013-01-21 09:41:05
【问题描述】:

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

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

我用来获取 1 个频道的 Now/Next 详细信息的 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

对于我只想提取 2 条记录的查询来说,这似乎相当复杂,其中第一条记录的开始时间早于(或等于)当前时间,结束时间晚于当前时间(现在),而第二条记录有与第一个 (Next) 的结束时间匹配的开始时间。

我只是想知道是否有更有效的方法来查询这种情况。

epg_event 表是使用以下内容创建的(为了说明架构)...

CREATE TABLE [EPG_EVENT] (
    [oid] integer PRIMARY KEY,
    [title] varchar(50),
    [subtitle] varchar(50),
    [description] varchar(50),
    [start_time] datetime,
    [end_time] datetime,
    [channel_oid] int,
    [unique_id] varchar(50),
    [rating] varchar(50),
    [original_air_date] datetime,
    [season] int,
    [episode] int,
    [dvb_service_event_id] int,
    [dvb_table_version] int,
    [genres] varchar(50)
)

显示的查询将返回...

_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

【问题讨论】:

  • 这必须在 Jelly Bean 之前的 Android 版本中工作吗? (您的查询没有。)
  • @CL。 :我已经编辑了问题以显示用于表格的CREATE TABLE。至于它在 Jelly Bean 之前的版本上工作,我可以向你保证它确实 - 我运行 Froyo 的 HTC Desire 运行良好(尽管速度很慢)。

标签: sqlite android-sqlite


【解决方案1】:

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

    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

但是,这两个条件等价于演出还没有结束的条件,或者:

    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
    GROUP BY a.channel_oid

现在,您在这里按已知的 channel_oid 过滤,但 GROUP BY 它 - 为什么?应该简化为

    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_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

要使其快速运行,请确保创建正确的索引。 This answer 可以为您提供一些如何优化它的想法,但乍一看,您至少应该在 epg_event 表上有以下复合索引:(channel_oid, start_time)(channel_oid, end_time)

【讨论】:

  • 谢谢。实际上,我的原始查询得到了一些帮助,因为 SQL 不是我的强项——我不知道帮助我的人为什么使用 GROUP BY。我已将查询压缩为您建议的查询,尽管它仅返回 1 条记录(正在显示的一条),因此我重新添加了 UNION 并且它可以工作。然而,真正的解决方法是复合索引——没有它们,您的精简查询不会明显更快,但是当我添加它们时,它确实有所作为(1-2 秒而不是 20-30 秒)。再次感谢。
  • 很高兴听到它对您有所帮助!复合索引真的可以让你开心:-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-23
  • 1970-01-01
  • 1970-01-01
  • 2016-04-26
  • 2013-02-10
  • 1970-01-01
相关资源
最近更新 更多