Skip to content

Perf: add extra index to notification table #32395

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

Merged
merged 2 commits into from
Nov 13, 2024

Conversation

BoYanZh
Copy link
Contributor

@BoYanZh BoYanZh commented Oct 31, 2024

Index SQL: CREATE INDEX u_s_uu ON notification(user_id, status, updated_unix);

The naming follows action.go in the same dir.

I am unsure which version I should add SQL to the migration folder, so I have not modified it.

Fix #32390

@GiteaBot GiteaBot added the lgtm/need 2 This PR needs two approvals by maintainers to be considered for merging. label Oct 31, 2024
@github-actions github-actions bot added the modifies/go Pull requests that update Go code label Oct 31, 2024
@lunny
Copy link
Member

lunny commented Oct 31, 2024

Migrations are necessary. You need add one line in migrations.go.

@lunny lunny added the performance/speed performance issues with slow downs label Oct 31, 2024
@pull-request-size pull-request-size bot added size/M and removed size/S labels Oct 31, 2024
@lunny lunny added this to the 1.23.0 milestone Nov 1, 2024
@pull-request-size pull-request-size bot added size/L and removed size/M labels Nov 1, 2024
@BoYanZh BoYanZh force-pushed the notification-index branch from a529100 to 1283d41 Compare November 1, 2024 03:36
@lunny lunny changed the title feat: add extra index to notification table (#32390) feat: add extra index to notification table Nov 1, 2024
@lunny lunny changed the title feat: add extra index to notification table Perf: add extra index to notification table Nov 1, 2024
@BoYanZh BoYanZh force-pushed the notification-index branch from 1283d41 to 09c4ea7 Compare November 1, 2024 21:50
@BoYanZh BoYanZh requested a review from lunny November 1, 2024 21:51
@BoYanZh BoYanZh requested a review from lunny November 2, 2024 03:13
@GiteaBot GiteaBot added lgtm/need 1 This PR needs approval from one additional maintainer to be merged. and removed lgtm/need 2 This PR needs two approvals by maintainers to be considered for merging. labels Nov 2, 2024
@lunny
Copy link
Member

lunny commented Nov 6, 2024

Please resolve the conflict and I cannot push to your branch.

@BoYanZh BoYanZh force-pushed the notification-index branch from 58b5203 to 949d4b2 Compare November 6, 2024 23:06
@BoYanZh BoYanZh force-pushed the notification-index branch from 949d4b2 to 4631f75 Compare November 6, 2024 23:08
@BoYanZh
Copy link
Contributor Author

BoYanZh commented Nov 6, 2024

Thank you for the notice! Done.

@GiteaBot GiteaBot added lgtm/done This PR has enough approvals to get merged. There are no important open reservations anymore. and removed lgtm/need 1 This PR needs approval from one additional maintainer to be merged. labels Nov 13, 2024
@lunny lunny added the reviewed/wait-merge This pull request is part of the merge queue. It will be merged soon. label Nov 13, 2024
@lunny lunny enabled auto-merge (squash) November 13, 2024 18:04
@lunny lunny merged commit ad22300 into go-gitea:main Nov 13, 2024
26 checks passed
@GiteaBot GiteaBot removed the reviewed/wait-merge This pull request is part of the merge queue. It will be merged soon. label Nov 13, 2024
zjjhot added a commit to zjjhot/gitea that referenced this pull request Nov 14, 2024
* giteaofficial/main:
  Refactor render system (go-gitea#32492)
  Fix nil panic if repo doesn't exist (go-gitea#32501)
  Bump CI,Flake and Snap to Node 22 (go-gitea#32487)
  Perf: add extra index to notification table (go-gitea#32395)
  Fix LFS route mock, realm, middleware names (go-gitea#32488)
DennisRasey pushed a commit to DennisRasey/forgejo that referenced this pull request Dec 6, 2024
- For the notifications page the unread and pinned notifications are
gathered for doer those that and are ordered by the updated unix.
MariaDB makes a bad decision (sometimes, for most users it does not make
this decision) with this query, it uses the index for the `updated_unix`
column to speed up this query, however this is not the correct index to
be taking, if the doer does not have more than 20 (the
page size) unread and pinned notifications combined MariaDB will
traverse the whole notifications table before it realizes that there are
no more notifications to be gathered. It instead should use the index
for the `user_id` column (this is what MariaDB already does for most
users), so the list that has to be traversed is limited to the doer's
notifications which is significantly less than the whole notifications
table.
- This is a different approach than what Gitea has taken to solve this
problem, which is to add a index to the (status, userid, updated_unix)
tuple (Ref: go-gitea/gitea#32395). Adding more
and more indexes is not a good way if we can use existing indexes to get
a query to a acceptable performance.
- The code cannot use `db.Find` as it's hard to add a index hint option
specifically for this query and not for the other instances that uses
`activities_model.FindNotificationOptions`.
- Only add a index hint for MySQL as I have not been able to test if
SQLite or PostgreSQL are smart enough to use the better index (as you
need a large enough dataset to test this meaningfully).
- Integration test added to ensure the SQL is run by all databases.

---

Performance numbers (from Codeberg's database - MariaDB
10.11.6-MariaDB-0+deb12u1):

Currently:
```sql
SELECT * FROM `notification` WHERE notification.user_id=26734 AND (notification.status=3 OR notification.status=1) ORDER BY notification.updated_unix DESC LIMIT 20;
(5.731 sec)
+------+-------------+--------------+-------+--------------------------------------------------+-------------------------------+---------+-------+---------+------------+----------+------------+-------------+
| id   | select_type | table        | type  | possible_keys                                    | key                           | key_len | ref   | rows    | r_rows     | filtered | r_filtered | Extra       |
+------+-------------+--------------+-------+--------------------------------------------------+-------------------------------+---------+-------+---------+------------+----------+------------+-------------+
|    1 | SIMPLE      | notification | index | IDX_notification_status,IDX_notification_user_id | IDX_notification_updated_unix | 8       | const | 1376836 | 1474066.00 |    50.03 |       0.00 | Using where |
+------+-------------+--------------+-------+--------------------------------------------------+-------------------------------+---------+-------+---------+------------+----------+------------+-------------+
```

Using the better index:
```sql
SELECT * FROM `notification` USE INDEX (IDX_notification_user_id) WHERE notification.user_id=26734 AND (notification.status=3 OR notification.status=1) ORDER BY notification.updated_unix DESC LIMIT 20;
(0.834 sec)

+------+-------------+--------------+--------+----------------------------------------------------------+--------------------------+---------+----------------------------------+-------+----------+----------+------------+----------------------------------------------+
| id   | select_type | table        | type   | possible_keys                                            | key                      | key_len | ref                              | rows  | r_rows   | filtered | r_filtered | Extra                                        |
+------+-------------+--------------+--------+----------------------------------------------------------+--------------------------+---------+----------------------------------+-------+----------+----------+------------+----------------------------------------------+
|    1 | PRIMARY     | notification | ref    | PRIMARY,IDX_notification_status,IDX_notification_user_id | IDX_notification_user_id | 8       | const                            | 22042 | 10756.00 |    50.03 |       0.02 | Using where; Using temporary; Using filesort |
|    1 | PRIMARY     | notification | eq_ref | PRIMARY                                                  | PRIMARY                  | 8       | gitea_production.notification.id | 1     | 1.00     |   100.00 |     100.00 |                                              |
+------+-------------+--------------+--------+----------------------------------------------------------+--------------------------+---------+----------------------------------+-------+----------+----------+------------+----------------------------------------------+
```
@BoYanZh BoYanZh deleted the notification-index branch February 9, 2025 10:38
@go-gitea go-gitea locked as resolved and limited conversation to collaborators Feb 12, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
lgtm/done This PR has enough approvals to get merged. There are no important open reservations anymore. modifies/go Pull requests that update Go code modifies/migrations performance/speed performance issues with slow downs
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Notification page becomes very slow when the table is very large
4 participants