Before
```sql
synapse=> explain SELECT event_id FROM events
LEFT JOIN rejections USING (event_id)
WHERE
room_id = '!...:matrix.org'
AND origin_server_ts <= 1620172800000
/**
* Make sure the event isn't an `outlier` because we have no way
* to later check whether it's next to a gap. `outliers` do not
* have entries in the `event_edges`, `event_forward_extremeties`,
* and `event_backward_extremities` tables to check against
* (used by `is_event_next_to_backward_gap` and `is_event_next_to_forward_gap`).
*/
AND NOT outlier
/* Make sure event is not rejected */
AND rejections.event_id IS NULL
/**
* First sort by the message timestamp. If the message timestamps are the
* same, we want the message that logically comes "next" (before/after
* the given timestamp) based on the DAG and its topological order (`depth`).
* Finally, we can tie-break based on when it was received on the server
* (`stream_ordering`).
*/
ORDER BY origin_server_ts DESC, depth DESC, stream_ordering DESC
LIMIT 1;
QUERY PLAN
------------------------------------------------------------------------------------------------------------------
Limit (cost=1075.38..2148.31 rows=1 width=66)
-> Incremental Sort (cost=1075.38..650197.88 rows=605 width=66)
Sort Key: events.origin_server_ts DESC, events.depth DESC, events.stream_ordering DESC
Presorted Key: events.origin_server_ts
-> Nested Loop Anti Join (cost=0.71..650170.66 rows=605 width=66)
-> Index Scan Backward using events_ts on events (cost=0.43..649835.91 rows=605 width=66)
Index Cond: (origin_server_ts <= '1620172800000'::bigint)
Filter: ((NOT outlier) AND (room_id = '!...:matrix.org'::text))
-> Index Only Scan using rejections_event_id_key on rejections (cost=0.28..0.55 rows=1 width=41)
Index Cond: (event_id = events.event_id)
```
Index
```sql
synapse=> create index rei_jtd_idx ON events(room_id, origin_server_ts) WHERE not outlier;
CREATE INDEX
synapse=> explain SELECT event_id FROM events
LEFT JOIN rejections USING (event_id)
WHERE
room_id = '!...:matrix.org'
AND origin_server_ts <= 1620172800000
/**
* Make sure the event isn't an `outlier` because we have no way
* to later check whether it's next to a gap. `outliers` do not
* have entries in the `event_edges`, `event_forward_extremeties`,
* and `event_backward_extremities` tables to check against
* (used by `is_event_next_to_backward_gap` and `is_event_next_to_forward_gap`).
*/
AND NOT outlier
/* Make sure event is not rejected */
AND rejections.event_id IS NULL
/**
* First sort by the message timestamp. If the message timestamps are the
* same, we want the message that logically comes "next" (before/after
* the given timestamp) based on the DAG and its topological order (`depth`).
* Finally, we can tie-break based on when it was received on the server
* (`stream_ordering`).
*/
ORDER BY origin_server_ts DESC, depth DESC, stream_ordering DESC
LIMIT 1;
QUERY PLAN
----------------------------------------------------------------------------------------------------------------------------------------
Limit (cost=5.44..10.08 rows=1 width=66)
-> Incremental Sort (cost=5.44..2819.10 rows=607 width=66)
Sort Key: events.origin_server_ts DESC, events.depth DESC, events.stream_ordering DESC
Presorted Key: events.origin_server_ts
-> Nested Loop Anti Join (cost=0.83..2791.78 rows=607 width=66)
-> Index Scan Backward using rei_jtd_idx on events (cost=0.56..2456.44 rows=607 width=66)
Index Cond: ((room_id = '!...:matrix.org'::text) AND (origin_server_ts <= '1620172800000'::bigint))
-> Index Only Scan using rejections_event_id_key on rejections (cost=0.28..0.55 rows=1 width=41)
Index Cond: (event_id = events.event_id)
```