【问题标题】:Why does it take me 40ms to select 1, but 500s to select 150?为什么我选择 1 需要 40ms,而选择 150 需要 500s?
【发布时间】:2017-10-29 20:33:24
【问题描述】:

我正在使用 SQLite 3。我有一个表 forums,有 150 行,还有一个表 posts,有大约 440 万行。每个帖子都属于一个论坛。

我想选择每个论坛最新帖子的时间戳。如果我要求一个最新的帖子,SELECT MAX(timestamp) FROM posts WHERE forum_id = 5,平均需要 40 毫秒。

我要求提供所有论坛的列表及其最新帖子

SELECT forums.name, max(posts.timestamp)
FROM posts
JOIN forums ON posts.forum_id = forums.id
GROUP BY forums.name

它有效,但需要 500 秒 -- 超过 12,000 倍的时间,而选择只有 150 倍。如果我只是在我的应用程序中编写一个循环来发出 150 个单独的选择查询,它会快得多。

我确实在posts.timestamp 上创建了一个索引,并在posts.timestamp, posts.forum_id 上创建了一个组合索引。它没有帮助。

我做错了什么?

【问题讨论】:

  • 你的索引是什么样的?
  • 你为什么不直接按forum_id分组?
  • 我的索引是CREATE INDEX forums_name ON posts (forum_id ASC)CREATE INDEX time_and_forum ON posts (timestamp DESC, forum_id ASC)
  • 你需要反转time_and_forum索引中的列

标签: sql sqlite group-by


【解决方案1】:

我会创建一个索引

create index ix_posts_forumid_timestamp on posts(forum_id, timestamp)

覆盖GROUP BY posts.forum_id查询如下

select forum_id, max(timestamp) 
from posts
group by forum_id 

如果查询在几秒钟内得到处理(应该是这样),那么您可以使用forums 测试连接:

select f.name, t.maxTime
from forums f
(
  select forum_id, max(timestamp) maxTime
  from posts
  group by forum_id 
) t on t.forum_id = f.forum_id

这样的查询也可以被另一个索引覆盖,但是由于您需要所有论坛,我想它不如第一个索引重要。最后,我相信拥有以下查询的索引也应该足够快

select f.name, max(p.timestamp) maxTime
from posts p
join forums f on f.forum_id = p.forum_id
group by p.forum_id 

【讨论】:

    【解决方案2】:

    forums.name 上的分组可能是问题所在,因为该列没有索引。尝试在posts.forum_id 上进行分组。

    如果您想通过输出获取论坛名称,您可以尝试以下操作:

    SELECT forums.name, t.latestTimeStamp
    From 
    (select posts.forum_id, max(posts.timestamp) as latestTimeStamp
    FROM posts
    GROUP BY forums.forum_id) as t
    JOIN forums ON t.forum_id = forums.id
    

    【讨论】:

    • 已经 7 分钟了,这个查询还在运行,所以我不确定是什么问题。
    • 单独的子选择也运行那么久吗?
    • 到目前为止,子选择运行了大约 3 分钟,并且仍在运行。
    猜你喜欢
    • 2021-02-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多