MM-53406: Fix userstore.count to avoid antijoin (#23953)

For MySQL, a query for type LEFT JOIN .. IS NULL
leads to a nested antijoin which leads to poor performance.

We fix this by rewriting the query to avoid the antijoin.

See the JIRA epic for more context behind this.

We also make another improvement to remove the DISTINCT
clause. It didn't serve any purpose since userids would
already be unique.

https://mattermost.atlassian.net/browse/MM-53406

```release-note
NONE
```
Этот коммит содержится в:
Agniva De Sarker
2023-07-10 10:19:44 +05:30
коммит произвёл GitHub
родитель 49e1d039f5
Коммит da3d5c73fe

Просмотреть файл

@@ -1304,19 +1304,24 @@ func (us SqlUserStore) PermanentDelete(userId string) error {
}
func (us SqlUserStore) Count(options model.UserCountOptions) (int64, error) {
isPostgreSQL := us.DriverName() == model.DatabaseDriverPostgres
query := us.getQueryBuilder().Select("COUNT(DISTINCT u.Id)").From("Users AS u")
query := us.getQueryBuilder().Select("COUNT(*)").From("Users AS u")
if !options.IncludeDeleted {
query = query.Where("u.DeleteAt = 0")
}
isPostgreSQL := us.DriverName() == model.DatabaseDriverPostgres
if options.IncludeBotAccounts {
if options.ExcludeRegularUsers {
query = query.Join("Bots ON u.Id = Bots.UserId")
}
} else {
query = query.LeftJoin("Bots ON u.Id = Bots.UserId").Where("Bots.UserId IS NULL")
if isPostgreSQL {
query = query.LeftJoin("Bots ON u.Id = Bots.UserId").Where("Bots.UserId IS NULL")
} else {
query = query.Where(sq.Expr("u.Id NOT IN (SELECT UserId FROM Bots)"))
}
if options.ExcludeRegularUsers {
// Currently this doesn't make sense because it will always return 0
return int64(0), errors.New("query with IncludeBotAccounts=false and excludeRegularUsers=true always return 0")