Schedule health_status on projects index removal
What does this MR do and why?
Schedule health_status on projects index removal
The index initially got introduced for filtering and sorting on health_status, but it no longer gets used by the optimizer. We can therefore drop it to reduce the amount of indexes on the issues table.
This index got introduced with !104094 (merged). However, the usage is low: https://dashboards.gitlab.net/goto/DfAwhCwHR?orgId=1https://dashboards.gitlab.net/goto/DfAwhCwHR?orgId=1.
And for the original query it got introduced, the query optimizer no longer uses the index, see:
- Query from the original MR: https://console.postgres.ai/gitlab/gitlab-production-main/sessions/42112/commands/129143
- Query on
gitlab-org/gitlab: https://console.postgres.ai/gitlab/gitlab-production-main/sessions/42112/commands/129145 - it prefers theindex_issues_on_work_item_type_id_project_id_created_at_stateindex and then sorts the result
As part of our guidelines on adding indexes: https://docs.gitlab.com/development/database/query_performance/#slow-list-views-and-apis we should reduce the amount of indexes, and not try to fit all possible combinations of sorting/filtering. This is a good use-case as the index is also barely used.
References
- Issue: #559053 (closed)
- FYI we also remove the index only on
health_status: #372205 (closed) !200195 (merged)
Screenshots or screen recordings
| Before | After |
|---|---|
How to set up and validate locally
Migration
bin/rails db:migrate
main: == [advisory_lock_connection] object_id: 145180, pg_backend_pid: 17141
main: == 20250804140514 RemoveIndexIssuesOnProjectHealthStatus: migrating ===========
main: -- index_exists?(:issues, [:project_id, :health_status, :id, :state_id, :work_item_type_id], {:name=>"index_issues_on_project_health_status_asc_work_item_type"})
main: -> 0.0281s
main: -- quote_column_name("index_issues_on_project_health_status_asc_work_item_type")
main: -> 0.0000s
main: == 20250804140514 RemoveIndexIssuesOnProjectHealthStatus: migrated (0.0612s) ==
main: == [advisory_lock_connection] object_id: 145180, pg_backend_pid: 17141
ci: == [advisory_lock_connection] object_id: 145180, pg_backend_pid: 17142
ci: == 20250804140514 RemoveIndexIssuesOnProjectHealthStatus: migrating ===========
ci: -- index_exists?(:issues, [:project_id, :health_status, :id, :state_id, :work_item_type_id], {:name=>"index_issues_on_project_health_status_asc_work_item_type"})
ci: -> 0.0123s
ci: -- quote_column_name("index_issues_on_project_health_status_asc_work_item_type")
ci: -> 0.0000s
ci: == 20250804140514 RemoveIndexIssuesOnProjectHealthStatus: migrated (0.0321s) ==
ci: == [advisory_lock_connection] object_id: 145180, pg_backend_pid: 17142
Checking scheduled indexes
gitlabhq_development=# select * from postgres_async_indexes order by id desc limit 1;
id | created_at | updated_at | name | definition | table_name | attempts | last_error
----+-------------------------------+-------------------------------+----------------------------------------------------------+------------------------------------------------------------------------------------+------------+----------+------------
40 | 2025-08-04 14:17:09.189892+00 | 2025-08-04 14:17:09.189892+00 | index_issues_on_project_health_status_asc_work_item_type | DROP INDEX CONCURRENTLY "index_issues_on_project_health_status_asc_work_item_type" | issues | 0 |
(1 row)
Reindexing
bundle exec rails gitlab:db:reindex
\d index_issues_on_project_health_status_asc_work_item_type
Did not find any relation named "index_issues_on_project_health_status_asc_work_item_type".
Rollback
rails db:migrate:down:main VERSION=20250804140514
main: == [advisory_lock_connection] object_id: 144880, pg_backend_pid: 17533
main: == 20250804140514 RemoveIndexIssuesOnProjectHealthStatus: reverting ===========
main: == 20250804140514 RemoveIndexIssuesOnProjectHealthStatus: reverted (0.0289s) ==
main: == [advisory_lock_connection] object_id: 144880, pg_backend_pid: 17533
MR acceptance checklist
Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.