message flags: Add where_starred helper and use it.

The previous query ended up doing a scan of all a user's UserMessage
rows, not just the ones tracked in the `starred` index.
This commit is contained in:
Tim Abbott 2018-08-21 15:03:00 -07:00
parent b93d5bd5e8
commit 887d20795f
2 changed files with 18 additions and 14 deletions

View File

@ -706,18 +706,13 @@ def get_muted_stream_ids(user_profile: UserProfile) -> List[int]:
return muted_stream_ids
def get_starred_message_ids(user_profile: UserProfile) -> List[int]:
rows = UserMessage.objects.filter(
return list(UserMessage.objects.filter(
user_profile=user_profile,
flags=UserMessage.flags.starred
).values(
'message_id'
).extra(
where=[UserMessage.where_starred()]
).order_by(
'message_id'
)
starred_message_ids = [
row['message_id']
for row in rows]
return starred_message_ids
).values_list('message_id', flat=True)[0:10000])
def get_raw_unread_data(user_profile: UserProfile) -> RawUnreadMessagesResult:

View File

@ -1543,13 +1543,22 @@ class AbstractUserMessage(models.Model):
@staticmethod
def where_unread() -> str:
# Use this for Django ORM queries where we are getting lots
# of rows. This custom SQL plays nice with our partial indexes.
# Grep the code for example usage.
#
# This optimization is only helpful for checking a flag being False.
# Use this for Django ORM queries to access unread message.
# This custom SQL plays nice with our partial indexes. Grep
# the code for example usage.
return 'flags & 1 = 0'
@staticmethod
def where_starred() -> str:
# Use this for Django ORM queries to access starred messages.
# This custom SQL plays nice with our partial indexes. Grep
# the code for example usage.
#
# The key detail is that e.g.
# UserMessage.objects.filter(user_profile=user_profile, flags=UserMessage.flags.starred)
# will generate a query involving `flags & 2 = 2`, which doesn't match our index.
return 'flags & 2 <> 0'
def flags_list(self) -> List[str]:
flags = int(self.flags)
return self.flags_list_for_flags(flags)