MM-55295: Improve DB performance of some APIs (#25318)
Load tests show that channelstore.GetMember and channelstore.GetMembersForUser are among the chief queries that take up CPU in the DB. In this PR, we attempt some strategic optimizations to reduce/optimize calls to channelstore.GetMember 1. Optimize `(a *App) HasPermissionToChannel` We replace GetChannelMember with GetAllChannelMembersForUser because it's cache backed. So although it gets more data, it does not hit the DB and saves some latency. 2. Optimize getPostsForChannelAroundLastUnread We repace getChannelMember with getChannelMemberOnly which is a lite version of the store call which queries just the ChannelMembers table. This is because in the app layer, we just use the LastViewedAt attribute. Therefore, there is no reason to join with 5 tables when a single table can do the job. 3. Optimize publishWebsocketEventForPermalinkPost We use GetAllChannelMembersById instead of GetChannelMembersPage which again joins with a lot of other tables. 4. Optimize countMentionsFromPost Again, we replace GetChannelMember which is a costly call joining multiple tables, with GetAllChannelMembersNotifyPropsForChannel which is cache-backed and gives us just what we need in the app layer - notify props. ```release-note Make small optimizations in several DB calls: - App.HasPermissionToChannel - getPostsForChannelAroundLastUnread - publishWebsocketEventForPermalinkPost - countMentionsFromPost ``` https://mattermost.atlassian.net/browse/MM-55295 --------- Co-authored-by: Mattermost Build <build@mattermost.com>
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
1ed5d87342
Коммит
ec88ab4ee9
@@ -907,10 +907,10 @@ func (s *TimerLayerChannelStore) GetAll(teamID string) ([]*model.Channel, error)
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (s *TimerLayerChannelStore) GetAllChannelMembersById(id string) ([]string, error) {
|
||||
func (s *TimerLayerChannelStore) GetAllChannelMemberIdsByChannelId(id string) ([]string, error) {
|
||||
start := time.Now()
|
||||
|
||||
result, err := s.ChannelStore.GetAllChannelMembersById(id)
|
||||
result, err := s.ChannelStore.GetAllChannelMemberIdsByChannelId(id)
|
||||
|
||||
elapsed := float64(time.Since(start)) / float64(time.Second)
|
||||
if s.Root.Metrics != nil {
|
||||
@@ -918,7 +918,7 @@ func (s *TimerLayerChannelStore) GetAllChannelMembersById(id string) ([]string,
|
||||
if err == nil {
|
||||
success = "true"
|
||||
}
|
||||
s.Root.Metrics.ObserveStoreMethodDuration("ChannelStore.GetAllChannelMembersById", success, elapsed)
|
||||
s.Root.Metrics.ObserveStoreMethodDuration("ChannelStore.GetAllChannelMemberIdsByChannelId", success, elapsed)
|
||||
}
|
||||
return result, err
|
||||
}
|
||||
@@ -1451,6 +1451,22 @@ func (s *TimerLayerChannelStore) GetMemberForPost(postID string, userID string)
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (s *TimerLayerChannelStore) GetMemberOnly(ctx context.Context, channelID string, userID string) (*model.ChannelMember, error) {
|
||||
start := time.Now()
|
||||
|
||||
result, err := s.ChannelStore.GetMemberOnly(ctx, channelID, userID)
|
||||
|
||||
elapsed := float64(time.Since(start)) / float64(time.Second)
|
||||
if s.Root.Metrics != nil {
|
||||
success := "false"
|
||||
if err == nil {
|
||||
success = "true"
|
||||
}
|
||||
s.Root.Metrics.ObserveStoreMethodDuration("ChannelStore.GetMemberOnly", success, elapsed)
|
||||
}
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (s *TimerLayerChannelStore) GetMembers(channelID string, offset int, limit int) (model.ChannelMembers, error) {
|
||||
start := time.Now()
|
||||
|
||||
|
||||
Ссылка в новой задаче
Block a user