Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimize queries and indexes on posts table #13217

Merged
merged 7 commits into from
Jan 10, 2020

Conversation

Pomyk
Copy link
Contributor

@Pomyk Pomyk commented Nov 26, 2019

Summary

Added RootId column to two indexes. Query in getParentPosts split into
two queries - for big channels can be ~1000x times faster in MySQL, but
a bit slower in PostgreSQL.
Rewritten query in GetPostsSince for MySQL - around 20% faster.
Benchmark results (/1 - 140k posts in channel, /2 - 800 posts):

benchmark                                                         old ns/op      new ns/op     delta
BenchmarkPosts/postgres/GetFlaggedPostsForTeam/1-16               12068006       12130615      +0.52%
BenchmarkPosts/postgres/GetFlaggedPostsForChannel/1-16            7334992        7388359       +0.73%
BenchmarkPosts/postgres/GetPosts(skipThreads=true)/1-16           1845547        1979362       +7.25%
BenchmarkPosts/postgres/GetPosts(skipThreads=false)/1-16          2260061        2595112       +14.82%
BenchmarkPosts/postgres/GetPostsSince(skipThreads=true)/1-16      38510212       40625368      +5.49%
BenchmarkPosts/postgres/GetPostsSince(skipThreads=false)/1-16     32389821       32581044      +0.59%
BenchmarkPosts/postgres/GetFlaggedPostsForTeam/2-16               1604215        1584941       -1.20%
BenchmarkPosts/postgres/GetFlaggedPostsForChannel/2-16            1278623        1277473       -0.09%
BenchmarkPosts/postgres/GetPosts(skipThreads=true)/2-16           1921049        1984581       +3.31%
BenchmarkPosts/postgres/GetPosts(skipThreads=false)/2-16          3478147        3000086       -13.74%
BenchmarkPosts/postgres/GetPostsSince(skipThreads=true)/2-16      4813332        5198276       +8.00%
BenchmarkPosts/postgres/GetPostsSince(skipThreads=false)/2-16     3475847        3816201       +9.79%
BenchmarkPosts/mysql/GetFlaggedPostsForTeam/1-16                  9674132        9708361       +0.35%
BenchmarkPosts/mysql/GetFlaggedPostsForChannel/1-16               5780763        5818874       +0.66%
BenchmarkPosts/mysql/GetPosts(skipThreads=true)/1-16              2261194        2268826       +0.34%
BenchmarkPosts/mysql/GetPosts(skipThreads=false)/1-16             2371804023     3184120       -99.87%
BenchmarkPosts/mysql/GetPostsSince(skipThreads=true)/1-16         35552813       27709811      -22.06%
BenchmarkPosts/mysql/GetPostsSince(skipThreads=false)/1-16        28758400       22622865      -21.33%
BenchmarkPosts/mysql/GetFlaggedPostsForTeam/2-16                  1174064        1205933       +2.71%
BenchmarkPosts/mysql/GetFlaggedPostsForChannel/2-16               1007026        1091551       +8.39%
BenchmarkPosts/mysql/GetPosts(skipThreads=true)/2-16              2274397        2408730       +5.91%
BenchmarkPosts/mysql/GetPosts(skipThreads=false)/2-16             7454395        2542741       -65.89%
BenchmarkPosts/mysql/GetPostsSince(skipThreads=true)/2-16         8879200        6843435       -22.93%
BenchmarkPosts/mysql/GetPostsSince(skipThreads=false)/2-16        6293932        5373276       -14.63%

Added RootId column to two indexes. Query in getParentPosts split into
two queries - for big channels can be ~1000x times faster in MySQL, but
a bit slower in PostgreSQL.
Rewritten query in GetPostsSince for MySQL - around 20% faster.
Benchmark results (/1 - 140k posts in channel, /2 - 800 posts):

benchmark                                                         old ns/op      new ns/op     delta
BenchmarkPosts/postgres/GetFlaggedPostsForTeam/1-16               12068006       12130615      +0.52%
BenchmarkPosts/postgres/GetFlaggedPostsForChannel/1-16            7334992        7388359       +0.73%
BenchmarkPosts/postgres/GetPosts(skipThreads=true)/1-16           1845547        1979362       +7.25%
BenchmarkPosts/postgres/GetPosts(skipThreads=false)/1-16          2260061        2595112       +14.82%
BenchmarkPosts/postgres/GetPostsSince(skipThreads=true)/1-16      38510212       40625368      +5.49%
BenchmarkPosts/postgres/GetPostsSince(skipThreads=false)/1-16     32389821       32581044      +0.59%
BenchmarkPosts/postgres/GetFlaggedPostsForTeam/2-16               1604215        1584941       -1.20%
BenchmarkPosts/postgres/GetFlaggedPostsForChannel/2-16            1278623        1277473       -0.09%
BenchmarkPosts/postgres/GetPosts(skipThreads=true)/2-16           1921049        1984581       +3.31%
BenchmarkPosts/postgres/GetPosts(skipThreads=false)/2-16          3478147        3000086       -13.74%
BenchmarkPosts/postgres/GetPostsSince(skipThreads=true)/2-16      4813332        5198276       +8.00%
BenchmarkPosts/postgres/GetPostsSince(skipThreads=false)/2-16     3475847        3816201       +9.79%
BenchmarkPosts/mysql/GetFlaggedPostsForTeam/1-16                  9674132        9708361       +0.35%
BenchmarkPosts/mysql/GetFlaggedPostsForChannel/1-16               5780763        5818874       +0.66%
BenchmarkPosts/mysql/GetPosts(skipThreads=true)/1-16              2261194        2268826       +0.34%
BenchmarkPosts/mysql/GetPosts(skipThreads=false)/1-16             2371804023     3184120       -99.87%
BenchmarkPosts/mysql/GetPostsSince(skipThreads=true)/1-16         35552813       27709811      -22.06%
BenchmarkPosts/mysql/GetPostsSince(skipThreads=false)/1-16        28758400       22622865      -21.33%
BenchmarkPosts/mysql/GetFlaggedPostsForTeam/2-16                  1174064        1205933       +2.71%
BenchmarkPosts/mysql/GetFlaggedPostsForChannel/2-16               1007026        1091551       +8.39%
BenchmarkPosts/mysql/GetPosts(skipThreads=true)/2-16              2274397        2408730       +5.91%
BenchmarkPosts/mysql/GetPosts(skipThreads=false)/2-16             7454395        2542741       -65.89%
BenchmarkPosts/mysql/GetPostsSince(skipThreads=true)/2-16         8879200        6843435       -22.93%
BenchmarkPosts/mysql/GetPostsSince(skipThreads=false)/2-16        6293932        5373276       -14.63%
@hanzei hanzei added the Work In Progress Not yet ready for review label Nov 26, 2019
@mattermod
Copy link
Contributor

This issue has been automatically labelled "stale" because it hasn't had recent activity.
A core team member will check in on the status of the PR to help with questions.
Thank you for your contribution!

/cc @jasonblais @hanzei

@hanzei hanzei added 2: Dev Review Requires review by a developer and removed Lifecycle/1:stale Work In Progress Not yet ready for review labels Dec 7, 2019
@hanzei
Copy link
Contributor

hanzei commented Dec 7, 2019

Sorry for the delay @Pomyk. I'm queuing your PR for dev review.

Copy link
Contributor

@reflog reflog left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Pomyk - looks great! Can you sync with master please?
@lieut-data - what do you think?

@Pomyk
Copy link
Contributor Author

Pomyk commented Dec 8, 2019

Synced. I wanted to check one more edge case - threads with a lot of responses.

@Pomyk Pomyk marked this pull request as ready for review December 9, 2019 11:10
@Pomyk Pomyk changed the title WIP: Optimize queries and indexes on posts table Optimize queries and indexes on posts table Dec 9, 2019
@Pomyk
Copy link
Contributor Author

Pomyk commented Dec 9, 2019

With a big thread it's still possible for MySQL to choose a slow plan with index merge, but it's a rather small edge case. I have also found some other small optimizations for posts but will make another PR for that.

@lieut-data
Copy link
Member

@Pomyk / @reflog, if needed, I can provide a more holistic review, but for now let me make sure to surface the history of optimizing this particular function: https://community.mattermost.com/core/pl/ezfwp364ct8bbewbji3ikpusrr and then https://community.mattermost.com/core/pl/n8bfq7wq77rkff8mgrrstqeuye. TLDR; customers that eschew threads altogether ran into severe performance issues from my original changes.

Not saying that will happen here, but just wanted to call out the context.

@Pomyk
Copy link
Contributor Author

Pomyk commented Dec 10, 2019

@lieut-data I've read that, it was one of the reasons I looked at that function. The proposed solution should work very well in case of small amount of threads as it loads root ids separately. The main downside is 5-20% slower execution on postgresql due to two queries instead of one.

@streamer45
Copy link
Contributor

The main downside is 5-20% slower execution on postgresql due to two queries instead of one.

If that's the only problem we could probably leverage DriverName() and keep the old query for postgresql.

@Pomyk
Copy link
Contributor Author

Pomyk commented Dec 16, 2019

Restored old version of getParentsPosts for postgres. Updated benchmark results:

benchmark                                                         old ns/op      new ns/op     delta
BenchmarkPosts/mysql/GetFlaggedPostsForChannel/1-16               5971511        5935143       -0.61%
BenchmarkPosts/mysql/GetFlaggedPostsForChannel/2-16               967008         985724        +1.94%
BenchmarkPosts/mysql/GetFlaggedPostsForTeam/1-16                  9505963        9625565       +1.26%
BenchmarkPosts/mysql/GetFlaggedPostsForTeam/2-16                  1150789        1168789       +1.56%
BenchmarkPosts/mysql/GetPostsSince(skipThreads=false)/1-16        25934340       23139905      -10.78%
BenchmarkPosts/mysql/GetPostsSince(skipThreads=false)/2-16        6146086        5450641       -11.32%
BenchmarkPosts/mysql/GetPostsSince(skipThreads=true)/1-16         32204145       28748512      -10.73%
BenchmarkPosts/mysql/GetPostsSince(skipThreads=true)/2-16         8418128        6573381       -21.91%
BenchmarkPosts/mysql/GetPosts(skipThreads=false)/1-16             2158266585     3529370       -99.84%
BenchmarkPosts/mysql/GetPosts(skipThreads=false)/2-16             7268547        2581119       -64.49%
BenchmarkPosts/mysql/GetPosts(skipThreads=true)/1-16              2281773        2377660       +4.20%
BenchmarkPosts/mysql/GetPosts(skipThreads=true)/2-16              2236679        2274708       +1.70%
BenchmarkPosts/postgres/GetFlaggedPostsForChannel/1-16            8089729        7382772       -8.74%
BenchmarkPosts/postgres/GetFlaggedPostsForChannel/2-16            1269485        1145514       -9.77%
BenchmarkPosts/postgres/GetFlaggedPostsForTeam/1-16               12959316       12305607      -5.04%
BenchmarkPosts/postgres/GetFlaggedPostsForTeam/2-16               1568316        1547614       -1.32%
BenchmarkPosts/postgres/GetPostsSince(skipThreads=false)/1-16     33482719       33110482      -1.11%
BenchmarkPosts/postgres/GetPostsSince(skipThreads=false)/2-16     3521149        3642925       +3.46%
BenchmarkPosts/postgres/GetPostsSince(skipThreads=true)/1-16      39402112       39291324      -0.28%
BenchmarkPosts/postgres/GetPostsSince(skipThreads=true)/2-16      4971702        5122663       +3.04%
BenchmarkPosts/postgres/GetPosts(skipThreads=false)/1-16          2569493        2508554       -2.37%
BenchmarkPosts/postgres/GetPosts(skipThreads=false)/2-16          2875447        2830292       -1.57%
BenchmarkPosts/postgres/GetPosts(skipThreads=true)/1-16           1991243        1928802       -3.14%
BenchmarkPosts/postgres/GetPosts(skipThreads=true)/2-16           2066719        1965796       -4.88%

store/sqlstore/post_store.go Outdated Show resolved Hide resolved
store/sqlstore/post_store.go Outdated Show resolved Hide resolved
@streamer45
Copy link
Contributor

Overall looks great, thanks @Pomyk 🎉 , just a couple of suggestions.

@streamer45 streamer45 added 3: QA Review Requires review by a QA tester. May occur at the same time as Dev Review and removed 2: Dev Review Requires review by a developer labels Dec 16, 2019
@lindy65 lindy65 added the Setup Cloud Test Server Setup an on-prem test server label Dec 17, 2019
@lindy65 lindy65 added Setup Cloud Test Server Setup an on-prem test server and removed Setup Cloud Test Server Setup an on-prem test server labels Dec 17, 2019
@mattermost mattermost deleted a comment from mattermod Dec 17, 2019
@lindy65 lindy65 removed the Setup Cloud Test Server Setup an on-prem test server label Dec 17, 2019
@mattermod
Copy link
Contributor

Test server destroyed

@lindy65 lindy65 added the Setup Cloud Test Server Setup an on-prem test server label Dec 17, 2019
@Pomyk
Copy link
Contributor Author

Pomyk commented Dec 17, 2019

@grundleborg pointed out that changing indexes on Posts table can take a long time for some clients, so it might not be a good idea to do it here. Both postgresql and mysql have the ability to add indexes concurrently but it's not used in mattermost.

@lindy65 lindy65 removed the Setup Cloud Test Server Setup an on-prem test server label Dec 18, 2019
@mattermod
Copy link
Contributor

Test server destroyed

@agnivade
Copy link
Member

Hello @Pomyk - sorry to jump in here. I just have a small request: could you please post the code used for the benchmark in the PR commit message ? So that it remains there for posterity. Thanks !

@Pomyk
Copy link
Contributor Author

Pomyk commented Dec 19, 2019

@agnivade
Copy link
Member

Thanks ! I was wondering how do we include that code as part of this PR.

I would think it would be okay to include micro-benchmarks like these in the codebase itself so that future improvements can be easily checked. It can be done in a future PR ofcourse. Doesn't need to block this one. But this change has some numbers included in it, and I'm afraid if we lose track of how to reliably get those numbers again, somebody in future might have a hard time.

@streamer45 @lieut-data - thoughts ?

@jasonblais
Copy link
Contributor

jasonblais commented Dec 21, 2019

Here's a Jira ticket to review and test the changes for this PR. Thanks @Pomyk for the contribution! Note that the review may not occur until a few weeks from now

@lindy65
Copy link
Contributor

lindy65 commented Jan 9, 2020

@Pomyk @streamer45

Can you help with test steps / information for this PR please?

@reflog
Copy link
Contributor

reflog commented Jan 9, 2020

@lindy65 I don't think it's QA testable, it's a performance change that will be tested during load-testing

@streamer45
Copy link
Contributor

@lindy65 I don't think it's QA testable, it's a performance change that will be tested during load-testing

Agreed. From a QA point of view I would probably only test that fetching posts/threads is working as expected since we are touching that part.

Copy link
Contributor

@lindy65 lindy65 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @reflog @streamer45 - passing this from QA's perspective then 👍

@lindy65 lindy65 added QA/Review Done QA review is completed but other reviews are outstanding (exception to usual process) and removed 3: QA Review Requires review by a QA tester. May occur at the same time as Dev Review labels Jan 9, 2020
@agnivade agnivade added 4: Reviews Complete All reviewers have approved the pull request and removed Lifecycle/frozen QA/Review Done QA review is completed but other reviews are outstanding (exception to usual process) labels Jan 10, 2020
@agnivade
Copy link
Member

Thanks @Pomyk !

@agnivade agnivade merged commit c41e9d9 into mattermost:master Jan 10, 2020
@amyblais amyblais added Changelog/Not Needed Does not require a changelog entry Docs/Not Needed Does not require documentation labels Jan 10, 2020
@agnivade
Copy link
Member

Some results from prod:

poststore getposts

The commit should have gone in some time on 10th. There is no "marked" difference though. But maybe it's just the weekend and the traffic is low. I will continue to keep an eye.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
4: Reviews Complete All reviewers have approved the pull request Changelog/Not Needed Does not require a changelog entry Docs/Not Needed Does not require documentation
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

10 participants