Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
synapse
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Container Registry
Model registry
Monitor
Service Desk
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Maunium
synapse
Commits
7f78b383
Unverified
Commit
7f78b383
authored
2 years ago
by
Eric Eastwood
Committed by
GitHub
2 years ago
Browse files
Options
Downloads
Patches
Plain Diff
Optimize `filter_events_for_client` for faster `/messages` - v2 (#14527)
Fix #14108
parent
df390a8e
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
changelog.d/14527.misc
+1
-0
1 addition, 0 deletions
changelog.d/14527.misc
synapse/storage/databases/state/bg_updates.py
+79
-20
79 additions, 20 deletions
synapse/storage/databases/state/bg_updates.py
with
80 additions
and
20 deletions
changelog.d/14527.misc
0 → 100644
+
1
−
0
View file @
7f78b383
Speed-up `/messages` with `filter_events_for_client` optimizations.
This diff is collapsed.
Click to expand it.
synapse/storage/databases/state/bg_updates.py
+
79
−
20
View file @
7f78b383
...
@@ -93,13 +93,6 @@ class StateGroupBackgroundUpdateStore(SQLBaseStore):
...
@@ -93,13 +93,6 @@ class StateGroupBackgroundUpdateStore(SQLBaseStore):
results
:
Dict
[
int
,
MutableStateMap
[
str
]]
=
{
group
:
{}
for
group
in
groups
}
results
:
Dict
[
int
,
MutableStateMap
[
str
]]
=
{
group
:
{}
for
group
in
groups
}
where_clause
,
where_args
=
state_filter
.
make_sql_filter_clause
()
# Unless the filter clause is empty, we're going to append it after an
# existing where clause
if
where_clause
:
where_clause
=
"
AND (%s)
"
%
(
where_clause
,)
if
isinstance
(
self
.
database_engine
,
PostgresEngine
):
if
isinstance
(
self
.
database_engine
,
PostgresEngine
):
# Temporarily disable sequential scans in this transaction. This is
# Temporarily disable sequential scans in this transaction. This is
# a temporary hack until we can add the right indices in
# a temporary hack until we can add the right indices in
...
@@ -110,31 +103,91 @@ class StateGroupBackgroundUpdateStore(SQLBaseStore):
...
@@ -110,31 +103,91 @@ class StateGroupBackgroundUpdateStore(SQLBaseStore):
# against `state_groups_state` to fetch the latest state.
# against `state_groups_state` to fetch the latest state.
# It assumes that previous state groups are always numerically
# It assumes that previous state groups are always numerically
# lesser.
# lesser.
# The PARTITION is used to get the event_id in the greatest state
# group for the given type, state_key.
# This may return multiple rows per (type, state_key), but last_value
# This may return multiple rows per (type, state_key), but last_value
# should be the same.
# should be the same.
sql
=
"""
sql
=
"""
WITH RECURSIVE s
tate
(state_group) AS (
WITH RECURSIVE s
gs
(state_group) AS (
VALUES(?::bigint)
VALUES(?::bigint)
UNION ALL
UNION ALL
SELECT prev_state_group FROM state_group_edges e, s
tate
s
SELECT prev_state_group FROM state_group_edges e, s
gs
s
WHERE s.state_group = e.state_group
WHERE s.state_group = e.state_group
)
)
SELECT DISTINCT ON (type, state_key)
%s
type, state_key, event_id
FROM state_groups_state
WHERE state_group IN (
SELECT state_group FROM state
) %s
ORDER BY type, state_key, state_group DESC
"""
"""
overall_select_query_args
:
List
[
Union
[
int
,
str
]]
=
[]
# This is an optimization to create a select clause per-condition. This
# makes the query planner a lot smarter on what rows should pull out in the
# first place and we end up with something that takes 10x less time to get a
# result.
use_condition_optimization
=
(
not
state_filter
.
include_others
and
not
state_filter
.
is_full
()
)
state_filter_condition_combos
:
List
[
Tuple
[
str
,
Optional
[
str
]]]
=
[]
# We don't need to caclculate this list if we're not using the condition
# optimization
if
use_condition_optimization
:
for
etype
,
state_keys
in
state_filter
.
types
.
items
():
if
state_keys
is
None
:
state_filter_condition_combos
.
append
((
etype
,
None
))
else
:
for
state_key
in
state_keys
:
state_filter_condition_combos
.
append
((
etype
,
state_key
))
# And here is the optimization itself. We don't want to do the optimization
# if there are too many individual conditions. 10 is an arbitrary number
# with no testing behind it but we do know that we specifically made this
# optimization for when we grab the necessary state out for
# `filter_events_for_client` which just uses 2 conditions
# (`EventTypes.RoomHistoryVisibility` and `EventTypes.Member`).
if
use_condition_optimization
and
len
(
state_filter_condition_combos
)
<
10
:
select_clause_list
:
List
[
str
]
=
[]
for
etype
,
skey
in
state_filter_condition_combos
:
if
skey
is
None
:
where_clause
=
"
(type = ?)
"
overall_select_query_args
.
extend
([
etype
])
else
:
where_clause
=
"
(type = ? AND state_key = ?)
"
overall_select_query_args
.
extend
([
etype
,
skey
])
select_clause_list
.
append
(
f
"""
(
SELECT DISTINCT ON (type, state_key)
type, state_key, event_id
FROM state_groups_state
INNER JOIN sgs USING (state_group)
WHERE
{
where_clause
}
ORDER BY type, state_key, state_group DESC
)
"""
)
overall_select_clause
=
"
UNION
"
.
join
(
select_clause_list
)
else
:
where_clause
,
where_args
=
state_filter
.
make_sql_filter_clause
()
# Unless the filter clause is empty, we're going to append it after an
# existing where clause
if
where_clause
:
where_clause
=
"
AND (%s)
"
%
(
where_clause
,)
overall_select_query_args
.
extend
(
where_args
)
overall_select_clause
=
f
"""
SELECT DISTINCT ON (type, state_key)
type, state_key, event_id
FROM state_groups_state
WHERE state_group IN (
SELECT state_group FROM sgs
)
{
where_clause
}
ORDER BY type, state_key, state_group DESC
"""
for
group
in
groups
:
for
group
in
groups
:
args
:
List
[
Union
[
int
,
str
]]
=
[
group
]
args
:
List
[
Union
[
int
,
str
]]
=
[
group
]
args
.
extend
(
where
_args
)
args
.
extend
(
overall_select_query
_args
)
txn
.
execute
(
sql
%
(
where
_clause
,),
args
)
txn
.
execute
(
sql
%
(
overall_select
_clause
,),
args
)
for
row
in
txn
:
for
row
in
txn
:
typ
,
state_key
,
event_id
=
row
typ
,
state_key
,
event_id
=
row
key
=
(
intern_string
(
typ
),
intern_string
(
state_key
))
key
=
(
intern_string
(
typ
),
intern_string
(
state_key
))
...
@@ -142,6 +195,12 @@ class StateGroupBackgroundUpdateStore(SQLBaseStore):
...
@@ -142,6 +195,12 @@ class StateGroupBackgroundUpdateStore(SQLBaseStore):
else
:
else
:
max_entries_returned
=
state_filter
.
max_entries_returned
()
max_entries_returned
=
state_filter
.
max_entries_returned
()
where_clause
,
where_args
=
state_filter
.
make_sql_filter_clause
()
# Unless the filter clause is empty, we're going to append it after an
# existing where clause
if
where_clause
:
where_clause
=
"
AND (%s)
"
%
(
where_clause
,)
# We don't use WITH RECURSIVE on sqlite3 as there are distributions
# We don't use WITH RECURSIVE on sqlite3 as there are distributions
# that ship with an sqlite3 version that doesn't support it (e.g. wheezy)
# that ship with an sqlite3 version that doesn't support it (e.g. wheezy)
for
group
in
groups
:
for
group
in
groups
:
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment