mirror of https://github.com/zulip/zulip.git
730da55bf8
Before this commit, postgres would choose a non-optimal query plan to find all presence rows belonging to a realm. We now do an extra query to get the list of relevant user_ids, which allows the next query to take advantage of UserPresence's index on user_profile_id. Here is the query plan for the offending query (this particular query isn't verbatim from the code, but it's representative of the problem): explain analyze select client_id from zerver_userpresence INNER JOIN zerver_userprofile ON zerver_userprofile.id = zerver_userpresence.user_profile_id WHERE zerver_userprofile.is_active and zerver_userprofile.realm_id = 3; Hash Join (cost=149.66..506.82 rows=5007 width=4) (actual time=48.834..121.215 rows=5007 loops=1) Hash Cond: (zerver_userprofile.id = zerver_userpresence.user_profile_id) -> Seq Scan on zerver_userprofile (cost=0.00..260.11 rows=5369 width=4) (actual time=0.009..24.322 rows=5021 loops=1) Filter: (is_active AND (realm_id = 3)) Rows Removed by Filter: 3 -> Hash (cost=87.07..87.07 rows=5007 width=8) (actual time=48.789..48.789 rows=5010 loops=1) Buckets: 1024 Batches: 1 Memory Usage: 196kB -> Seq Scan on zerver_userpresence (cost=0.00..87.07 rows=5007 width=8) (actual time=0.007..24.355 rows=5010 loops=1) Total runtime: 145.063 ms You can see above that we're filtering on realm_id instead of using an index. When you decompose the query into two queries, the total time is about 100ms, for a savings of 33%. I imagine the savings would be even greater on an instance with lots of realms. This was tested on dev with one really large realm and one tiny realm. |
||
---|---|---|
.. | ||
fixtures | ||
lib | ||
management | ||
migrations | ||
templatetags | ||
tests | ||
tornado | ||
views | ||
webhooks | ||
worker | ||
__init__.py | ||
apps.py | ||
context_processors.py | ||
decorator.py | ||
filters.py | ||
forms.py | ||
logging_handlers.py | ||
middleware.py | ||
models.py | ||
signals.py | ||
static_header.txt | ||
storage.py |