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)  	}  | 
