229 создала trade_in_estimates_expires_at_idx — побайтовую копию
trade_in_estimates_expires_idx из 001 (pg_index: indkey/indclass/indoption/
indcollation совпадают, предиката нет у обоих, оба btree, ни один не привязан
к ограничению).
Число из тела задачи устарело: у дубля уже не 0 сканов, а 15, при этом
счётчик старого заморожен на 234 — планировщик перевёл весь живой трафик на
дубль. Причина физическая, не семантическая: свежесобранный индекс плотнее
(relpages 5 против 6), спуск по дереву дешевле. Нового запроса не появилось —
idx_tup_read/idx_scan у обоих одного порядка.
Опровергнуто обоснование самой 229: заявленный потребитель
(purge_expired_trade_in_data) на проде ни один из двух индексов не использует —
запрос сужен по created_by IS NULL и идёт через
idx_trade_in_estimates_created_by_created_at, expires_at остаётся Filter'ом.
Аргумента «оставить именно индекс из 229» нет, поэтому оставлен индекс из 001.
Планы ДО/ПОСЛЕ сняты на чистом PostgreSQL 16.4 с воспроизведённым перекосом
плотности: форма плана, Index Cond и Filter идентичны, меняется только имя
индекса и cost на одну страницу спуска.
DROP INDEX без CONCURRENTLY и без CASCADE: таблица 1061 строка / heap 1856 kB,
ACCESS EXCLUSIVE держится единицы миллисекунд; в pg_depend на индекс никто не
ссылается, гранты живут на таблице.