-
Notifications
You must be signed in to change notification settings - Fork 387
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Faster multiplayer room participation listing #11263
base: master
Are you sure you want to change the base?
Faster multiplayer room participation listing #11263
Conversation
|
fwiw adding the user,room index using table dumps from production: before:
after:
|
I think we should try adding the index first and see if it helps. If it didn't then proceed with this pr. @peppy |
try it with |
|
I've added the index. I think it will work short term, but if a user ends up participating in 1,000+ multiplayer rooms it will start to falter: > explain SELECT * FROM `multiplayer_rooms` WHERE `TYPE` in ('head_to_head', 'team_versus') and EXISTS (SELECT * FROM `multiplayer_rooms_high`
-> WHERE `multiplayer_rooms`.`id` = `multiplayer_rooms_high`.`room_id` and `user_id` = 1040328) and `multiplayer_rooms`.`deleted_at` IS NULL ORD
-> ER BY `ends_at` DESC, `id` DESC LIMIT 51\G;
***************************[ 1. row ]***************************
id | 1
select_type | SIMPLE
table | multiplayer_rooms_high
partitions | <null>
type | ref
possible_keys | multiplayer_rooms_high_room_id_user_id_unique,user_room
key | user_room
key_len | 4
ref | const
rows | 213
filtered | 100.0
Extra | Using index; Using temporary; Using filesort
***************************[ 2. row ]***************************
id | 1
select_type | SIMPLE
table | multiplayer_rooms
partitions | <null>
type | eq_ref
possible_keys | PRIMARY,multiplayer_rooms_type_category_ends_at_index
key | PRIMARY
key_len | 8
ref | osu.multiplayer_rooms_high.room_id
rows | 1
filtered | 5.63
Extra | Using where The |
@@ -500,6 +525,15 @@ public function recentParticipants(): array | |||
->all(); | |||
} | |||
|
|||
public function save(array $options = []) | |||
{ | |||
if ($this->exists && $this->isDirty('ends_at')) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't it make more sense for this column to be called ended_at
similar to scores
table, and have it set when the score is set, rather than when the room is saved?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I get that, but I'm proposing not doing that. I think it makes more sense to list based on the user's last play rather than the time the room was closed? Will make much more sense for the profile page usage.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The display will need to be adjusted a bit since the part with the room state and closing time are meant to make sense together, and it would be weird if all the times started showing other of order.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I dunno, I think it would still make sense to me 😅
is this still needed? also is this result correct?
|
I'm doing a bit more testing on this at the moment, and it's really depending on how the records are spread out 😐 |
Duplicates
ends_at
tomultiplayer_rooms_high
and uses it for sort order.The existing issue is ordering on
multiplayer_rooms
while the existence check usesmultiplayer_rooms_high
can result in too many records being scanned to get enough matching rows. The issue doesn't exist if there's no sort order, or the required rows are all early in the sorting order.I made the listing a separate scope so other queries that don't have the issue can skip the join mess.
2024_06_11_000001_add_ends_at_to_multiplayer_rooms_high
CREATE INDEX participated_rooms ON multiplayer_rooms_high (ends_at DESC, room_id DESC, user_id)
UPDATE multiplayer_rooms_high h INNER JOIN multiplayer_rooms r ON h.room_id = r.id SET h.ends_at = r.ends_at