summaryrefslogtreecommitdiffstats
path: root/store/sqlstore/post_store.go
diff options
context:
space:
mode:
authorJesse Hallam <jesse.hallam@gmail.com>2018-03-16 11:10:14 -0400
committerChristopher Speller <crspeller@gmail.com>2018-03-16 08:10:14 -0700
commit4b675b347b5241def7807fab5e01ce9b98531815 (patch)
tree8cc592a157200b458f36b973fe303e739c995f5a /store/sqlstore/post_store.go
parenta41a9500bc8cee75740db81017982fdae5d14d77 (diff)
downloadchat-4b675b347b5241def7807fab5e01ce9b98531815.tar.gz
chat-4b675b347b5241def7807fab5e01ce9b98531815.tar.bz2
chat-4b675b347b5241def7807fab5e01ce9b98531815.zip
MM-9770: rewrite getParentsPosts to improve performance (#8467)
* rename variables in testPostStoreGetPostsWithDetails This helps to clarify the structure of the posts under test. * clarify and expand existing testPostStoreGetPostsWithDetails assertions * expand testPostStoreGetPostsWithDetails assertions This verifies that replies to posts in the window, themselves not in the window (because of a non-zero offset) are still fetched. They were previously missing. * MM-9770: rewrite getParentsPosts to improve performance See discussion on ~developers-performance, but the basic idea here is to force the database to use the `PRIMARY` index when fetching posts instead of trying to filter down by channel and doing a scan.
Diffstat (limited to 'store/sqlstore/post_store.go')
-rw-r--r--store/sqlstore/post_store.go85
1 files changed, 62 insertions, 23 deletions
diff --git a/store/sqlstore/post_store.go b/store/sqlstore/post_store.go
index 92ee28ffa..3ff9a3e1b 100644
--- a/store/sqlstore/post_store.go
+++ b/store/sqlstore/post_store.go
@@ -687,31 +687,70 @@ func (s SqlPostStore) getRootPosts(channelId string, offset int, limit int) stor
func (s SqlPostStore) getParentsPosts(channelId string, offset int, limit int) store.StoreChannel {
return store.Do(func(result *store.StoreResult) {
var posts []*model.Post
- _, err := s.GetReplica().Select(&posts,
- `SELECT
- q2.*
+ _, err := s.GetReplica().Select(&posts, `
+ SELECT
+ *
FROM
- Posts q2
- INNER JOIN
- (SELECT DISTINCT
- q3.RootId
- FROM
- (SELECT
- RootId
- FROM
- Posts
- WHERE
- ChannelId = :ChannelId1
- AND DeleteAt = 0
- ORDER BY CreateAt DESC
- LIMIT :Limit OFFSET :Offset) q3
- WHERE q3.RootId != '') q1
- ON q1.RootId = q2.Id OR q1.RootId = q2.RootId
+ Posts
WHERE
- ChannelId = :ChannelId2
- AND DeleteAt = 0
- ORDER BY CreateAt`,
- map[string]interface{}{"ChannelId1": channelId, "Offset": offset, "Limit": limit, "ChannelId2": channelId})
+ Id IN (SELECT * FROM (
+ -- The root post of any replies in the window
+ (SELECT * FROM (
+ SELECT
+ CASE RootId
+ WHEN '' THEN NULL
+ ELSE RootId
+ END
+ FROM
+ Posts
+ WHERE
+ ChannelId = :ChannelId1
+ AND DeleteAt = 0
+ ORDER BY
+ CreateAt DESC
+ LIMIT :Limit1 OFFSET :Offset1
+ ) x )
+
+ UNION
+
+ -- The reply posts to all threads intersecting with the window, including replies
+ -- to root posts in the window itself.
+ (
+ SELECT
+ Id
+ FROM
+ Posts
+ WHERE RootId IN (SELECT * FROM (
+ SELECT
+ CASE RootId
+ -- If there is no RootId, return the post id itself to be considered
+ -- as a root post.
+ WHEN '' THEN Id
+ -- If there is a RootId, this post isn't a root post and return its
+ -- root to be considered as a root post.
+ ELSE RootId
+ END
+ FROM
+ Posts
+ WHERE
+ ChannelId = :ChannelId2
+ AND DeleteAt = 0
+ ORDER BY
+ CreateAt DESC
+ LIMIT :Limit2 OFFSET :Offset2
+ ) x )
+ )
+ ) x )
+ AND
+ DeleteAt = 0
+ `, map[string]interface{}{
+ "ChannelId1": channelId,
+ "ChannelId2": channelId,
+ "Offset1": offset,
+ "Offset2": offset,
+ "Limit1": limit,
+ "Limit2": limit,
+ })
if err != nil {
result.Err = model.NewAppError("SqlPostStore.GetLinearPosts", "store.sql_post.get_parents_posts.app_error", nil, "channelId="+channelId+" err="+err.Error(), http.StatusInternalServerError)
} else {