diff options
author | 2023-08-02 15:11:23 +0100 | |
---|---|---|
committer | 2023-08-02 16:11:23 +0200 | |
commit | 2cee8f2dd85f40be77be8ae07262af00aa46e940 (patch) | |
tree | 265bf22851ba7cdeaee51b6a47849152d29d2a61 | |
parent | [bugfix] handle HEAD requests more elegantly (#2055) (diff) | |
download | gotosocial-2cee8f2dd85f40be77be8ae07262af00aa46e940.tar.xz |
[bugfix] fix slow accounts / statuses using emojis lookups (#2056)
* update DeleteEmoji to use faster relational tables for status / account finding
Signed-off-by: kim <grufwub@gmail.com>
* update Get{Accounts,Statuses}UsingEmoji() to also use relational tables
Signed-off-by: kim <grufwub@gmail.com>
* remove the now unneeded tags relation from newStatusQ()
Signed-off-by: kim <grufwub@gmail.com>
* fix table names
Signed-off-by: kim <grufwub@gmail.com>
* fix account and status selects using emojis
Signed-off-by: kim <grufwub@gmail.com>
---------
Signed-off-by: kim <grufwub@gmail.com>
-rw-r--r-- | internal/db/bundb/account.go | 25 | ||||
-rw-r--r-- | internal/db/bundb/emoji.go | 86 | ||||
-rw-r--r-- | internal/db/bundb/status.go | 26 |
3 files changed, 45 insertions, 92 deletions
diff --git a/internal/db/bundb/account.go b/internal/db/bundb/account.go index e57c01a82..6a47418b7 100644 --- a/internal/db/bundb/account.go +++ b/internal/db/bundb/account.go @@ -468,24 +468,13 @@ func (a *accountDB) GetAccountCustomCSSByUsername(ctx context.Context, username func (a *accountDB) GetAccountsUsingEmoji(ctx context.Context, emojiID string) ([]*gtsmodel.Account, error) { var accountIDs []string - // Create SELECT account query. - q := a.db.NewSelect(). - Table("accounts"). - Column("id") - - // Append a WHERE LIKE clause to the query - // that checks the `emoji` column for any - // text containing this specific emoji ID. - // - // The reason we do this instead of doing a - // `WHERE ? IN (emojis)` is that the latter - // ends up being much MUCH slower, and the - // database stores this ID-array-column as - // text anyways, allowing a simple LIKE query. - q = whereLike(q, "emojis", emojiID) - - // Execute the query, scanning destination into accountIDs. - if _, err := q.Exec(ctx, &accountIDs); err != nil { + // SELECT all accounts using this emoji, + // using a relational table for improved perf. + if _, err := a.db.NewSelect(). + Table("account_to_emojis"). + Column("account_id"). + Where("? = ?", bun.Ident("emoji_id"), emojiID). + Exec(ctx, &accountIDs); err != nil { return nil, a.db.ProcessError(err) } diff --git a/internal/db/bundb/emoji.go b/internal/db/bundb/emoji.go index 04f22b6e9..e675339a2 100644 --- a/internal/db/bundb/emoji.go +++ b/internal/db/bundb/emoji.go @@ -106,47 +106,36 @@ func (e *emojiDB) DeleteEmojiByID(ctx context.Context, id string) error { } return e.db.RunInTx(ctx, func(tx bun.Tx) error { - // delete links between this emoji and any statuses that use it - // TODO: remove when we delete this table - if _, err := tx. - NewDelete(). - TableExpr("? AS ?", bun.Ident("status_to_emojis"), bun.Ident("status_to_emoji")). - Where("? = ?", bun.Ident("status_to_emoji.emoji_id"), id). - Exec(ctx); err != nil { - return err - } - - // delete links between this emoji and any accounts that use it - // TODO: remove when we delete this table - if _, err := tx. - NewDelete(). - TableExpr("? AS ?", bun.Ident("account_to_emojis"), bun.Ident("account_to_emoji")). - Where("? = ?", bun.Ident("account_to_emoji.emoji_id"), id). - Exec(ctx); err != nil { + // Delete relational links between this emoji + // and any statuses using it, returning the + // status IDs so we can later update them. + if _, err := tx.NewDelete(). + Table("status_to_emojis"). + Where("? = ?", bun.Ident("emoji_id"), id). + Returning("status_id"). + Exec(ctx, &statusIDs); err != nil { return err } - // Prepare a SELECT query with a WHERE LIKE - // that checks the `emoji` column for any - // text containing this specific emoji ID. - // - // (see GetStatusesUsingEmoji() for details.) - aq := tx.NewSelect().Table("accounts").Column("id") - aq = whereLike(aq, "emojis", id) - - // Select all accounts using this emoji into accountIDss. - if _, err := aq.Exec(ctx, &accountIDs); err != nil { + // Delete relational links between this emoji + // and any accounts using it, returning the + // account IDs so we can later update them. + if _, err := tx.NewDelete(). + Table("account_to_emojis"). + Where("? = ?", bun.Ident("emoji_id"), id). + Returning("account_id"). + Exec(ctx, &accountIDs); err != nil { return err } - for _, id := range accountIDs { + for _, id := range statusIDs { var emojiIDs []string - // Select account with ID. + // Select statuses with ID. if _, err := tx.NewSelect(). - Table("accounts"). + Table("statuses"). Column("emojis"). - Where("id = ?", id). + Where("? = ?", bun.Ident("id"), id). Exec(ctx); err != nil && err != sql.ErrNoRows { return err @@ -155,10 +144,10 @@ func (e *emojiDB) DeleteEmojiByID(ctx context.Context, id string) error { // Drop ID from account emojis. emojiIDs = dropID(emojiIDs, id) - // Update account emoji IDs. + // Update status emoji IDs. if _, err := tx.NewUpdate(). - Table("accounts"). - Where("id = ?", id). + Table("statuses"). + Where("? = ?", bun.Ident("id"), id). Set("emojis = ?", emojiIDs). Exec(ctx); err != nil && err != sql.ErrNoRows { @@ -166,27 +155,14 @@ func (e *emojiDB) DeleteEmojiByID(ctx context.Context, id string) error { } } - // Prepare a SELECT query with a WHERE LIKE - // that checks the `emoji` column for any - // text containing this specific emoji ID. - // - // (see GetStatusesUsingEmoji() for details.) - sq := tx.NewSelect().Table("statuses").Column("id") - sq = whereLike(sq, "emojis", id) - - // Select all statuses using this emoji into statusIDs. - if _, err := sq.Exec(ctx, &statusIDs); err != nil { - return err - } - - for _, id := range statusIDs { + for _, id := range accountIDs { var emojiIDs []string - // Select statuses with ID. + // Select account with ID. if _, err := tx.NewSelect(). - Table("statuses"). + Table("accounts"). Column("emojis"). - Where("id = ?", id). + Where("? = ?", bun.Ident("id"), id). Exec(ctx); err != nil && err != sql.ErrNoRows { return err @@ -195,10 +171,10 @@ func (e *emojiDB) DeleteEmojiByID(ctx context.Context, id string) error { // Drop ID from account emojis. emojiIDs = dropID(emojiIDs, id) - // Update status emoji IDs. + // Update account emoji IDs. if _, err := tx.NewUpdate(). - Table("statuses"). - Where("id = ?", id). + Table("accounts"). + Where("? = ?", bun.Ident("id"), id). Set("emojis = ?", emojiIDs). Exec(ctx); err != nil && err != sql.ErrNoRows { @@ -209,7 +185,7 @@ func (e *emojiDB) DeleteEmojiByID(ctx context.Context, id string) error { // Delete emoji from database. if _, err := tx.NewDelete(). Table("emojis"). - Where("id = ?", id). + Where("? = ?", bun.Ident("id"), id). Exec(ctx); err != nil { return err } diff --git a/internal/db/bundb/status.go b/internal/db/bundb/status.go index 0fef01736..c34074dd6 100644 --- a/internal/db/bundb/status.go +++ b/internal/db/bundb/status.go @@ -43,7 +43,6 @@ func (s *statusDB) newStatusQ(status interface{}) *bun.SelectQuery { return s.db. NewSelect(). Model(status). - Relation("Tags"). Relation("CreatedWithApplication") } @@ -440,24 +439,13 @@ func (s *statusDB) DeleteStatusByID(ctx context.Context, id string) error { func (s *statusDB) GetStatusesUsingEmoji(ctx context.Context, emojiID string) ([]*gtsmodel.Status, error) { var statusIDs []string - // Create SELECT status query. - q := s.db.NewSelect(). - Table("statuses"). - Column("id") - - // Append a WHERE LIKE clause to the query - // that checks the `emoji` column for any - // text containing this specific emoji ID. - // - // The reason we do this instead of doing a - // `WHERE ? IN (emojis)` is that the latter - // ends up being much MUCH slower, and the - // database stores this ID-array-column as - // text anyways, allowing a simple LIKE query. - q = whereLike(q, "emojis", emojiID) - - // Execute the query, scanning destination into statusIDs. - if _, err := q.Exec(ctx, &statusIDs); err != nil { + // SELECT all statuses using this emoji, + // using a relational table for improved perf. + if _, err := s.db.NewSelect(). + Table("status_to_emojis"). + Column("status_id"). + Where("? = ?", bun.Ident("emoji_id"), emojiID). + Exec(ctx, &statusIDs); err != nil { return nil, s.db.ProcessError(err) } |