Repository navigation
Drop redundant indexes on contentnode and file #6350
Description
❌ This issue is not open for contribution. Visit Contributing guidelines to learn about the contributing process and how to find suitable issues.
Overview
contentcuration_contentnode and contentcuration_file carry 12 indexes, about 275 GB, that production doesn't need: unscanned since stats were reset on 2026-06-09, or duplicating another index that serves the same lookups at the same cost. Eight are the varchar_pattern_ops _like twins Django adds to every indexed CharField, including Studio's char primary keys and foreign keys to them. Every insert, and every update that can't be done as a HOT update, writes to all of them. These indexes should be dropped.
Complexity: Medium
Target branch: hotfixes
Context
Production master, stats since 2026-06-09:
| Index | GB | Scans | Last scan |
|---|---|---|---|
contentcuration_contentnode_id_2b2d9339_like |
35.6 | 0 | — |
contentcuration_contentnode_original_channel_id_041c1412_uniq |
29.3 | 0 | — |
contentcuration_contentnode_original_channel_id_041c1412_like |
29.4 | 0 | — |
contentcuration_contentno_original_source_node_id_da1f3b83_uniq |
33.9 | 0 | — |
contentcuration_contentno_original_source_node_id_da1f3b83_like |
33.8 | 271 | 2026-06-09, all from a manual debugging job |
contentcuration_contentnode_content_id_2d487326_like |
34.0 | 0 | — |
contentcuration_contentnode_language_id_584857c7_like |
13.0 | 0 | — |
contentcuration_file_id_2b1c3d45_like |
20.2 | 245,764,090 | 2026-10-27; equality lookups file_pkey serves at the same cost |
contentcuration_file_checksum_b1b496dc_uniq |
15.8 | 29,915 | 2026-10-27; moves to file_checksum_file_size_idx after #6348 |
contentcuration_file_checksum_b1b496dc_like |
15.8 | 2 | 2026-08-08 |
contentcuration_file_contentnode_id_422a85ec_like |
8.2 | 0 | — |
contentcuration_file_07d5d9a8 (file_format_id) |
6.5 | 0 | — |
- The plain indexes on
content_id,language_idandfile.contentnode_idare in use and stay. varchar_pattern_opssupports=as well asLIKE. On production,EXPLAINgivescontentcuration_file_id_2b1c3d45_likeandfile_pkeythe same cost (0.69..8.71) forid = '…', and the planner breaks the tie towards_like;id = ANY(…)already usesfile_pkey. No code does a pattern lookup (__startswith,__contains,__regex) on anid.- Declaring an index in
Meta.indexesinstead ofdb_index=Truecreates no_liketwin:node_idalready does this (models.py:1934,:2867), andnode_id_idxhas no twin on production. Remove varchar_pattern_ops index for modality kolibri#14076 did the same formodality.
The Change
- A non-atomic migration should drop the 12 indexes with
DROP INDEX CONCURRENTLY, so reads and writes on both tables aren't blocked. - The model state should match the database:
original_channel_id,original_source_node_id,File.checksumandFile.file_formatshould have no index, whilecontent_id,ContentNode.languageandFile.contentnodeshould keep their plain index, declared inMeta.indexes. - The primary keys'
_liketwins have no representation in Django's model state, so their drops should be database-only operations.
Out of Scope
- The
file.slideshow_slideindex, pending a look at which slides exist in production.
Acceptance Criteria
General
- The
file.checksumpair ships only after Make file_checksum_file_size_idx unconditional again #6348 has been onmasterfor 7 days, with no increase inidx_scanoncontentcuration_file_checksum_b1b496dc_uniqover those 7 days - After deploy to
hotfixes, none of the 12 indexes in Context exist - The plain indexes on
content_id,language_idandfile.contentnode_idkeep their OIDs, so they weren't rebuilt -
makemigrations --checkreports no changes - In the 7 days after deploy to
master, the slow query log (log_min_duration_statement = 500ms) shows no new entries filtering on a column whose index was dropped
AI usage
Drafted with Claude Code, which measured index usage on production through read-only queries in the disposable debugging job and traced which code paths query each column. I chose which indexes to drop or keep, the gate on the checksum pair, and the scope.

Activity
[-]Drop unused indexes on contentnode and file[/-][+]Drop redundant indexes on contentnode and file[/+]