为什么选择1需要40ms,而选择150需要500?

时间:2017-10-29 20:33:24

标签: sql sqlite group-by

我使用的是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

它有效,但需要 500s - 超过12,000x,只能选择150x。如果我只是在我的应用程序中编写一个循环来发出150个单独的选择查询,那么它会更快。

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

我做错了什么?

2 个答案:

答案 0 :(得分:2)

我会创建一个索引

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 

答案 1 :(得分:1)

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