Consegui fazer isso, e o Postgres (e o Discourse!) parecem estar felizes.
Eu os limpei manualmente, tornando os URLs únicos com padrões ** conforme apropriado. Pode ter sido apenas um cache inofensivo onde eu poderia ter excluído os duplicados, mas não quis arriscar.
No meu caso, era apenas um índice, então reconstruir todos os índices provavelmente foi exagero, mas honestamente me senti melhor sabendo que peguei tudo.
Após algumas tentativas falhas de reconstrução, que levam cerca de 30 segundos cada e relatam um único problema, esta foi minha mágica SQL para obter uma lista completa de itens problemáticos instantaneamente:
discourse=# select topic_id, post_id, url, COUNT(*) from topic_links GROUP BY topic_id, post_id, url HAVING COUNT(*) > 1 order by topic_id, post_id;
topic_id | post_id | url | count
----------+---------+-------------------------------------------------------+-------
19200 | 88461 | http://hg.libsdl.org/SDL/rev/**533131e24aeb | 2
19207 | 88521 | http://hg.libsdl.org/SDL/rev/44a2e00e7c66 | 2
19255 | 88683 | http://lists.libsdl.org/__listinfo.cgi/sdl-libsdl.org | 2
19255 | 88683 | http://lists.libsdl.org/**listinfo.cgi/sdl-libsdl.org | 2
19523 | 90003 | http://twitter.com/Ironcode_Gaming | 2
(5 rows)
(5 itens problemáticos restantes nesta consulta, a título de exemplo.)
Então eu olharia cada post para ver o que havia e o que consertar:
select * from topic_links where topic_id=19255 and post_id=88683
e então consertaria um deles:
update public.topic_links set url='http://lists.libsdl.org/__listinfo.cgi/**sdl-libsdl.org' where id=275100;
Até que eu terminasse de consertar as coisas. ![]()
Eu provavelmente poderia ter feito alguma mágica de inner-join (ou talvez um pouco de Ruby) para obter tudo isso em uma única consulta, mas não sou um especialista e acabou não sendo horas de trabalho para fazer manualmente. Mas foi tedioso, para ser claro. ![]()
Então eu executei REINDEX DATABASE discourse; sem o CONCURRENTLY apenas para simplificar, apaguei alguns índices ccnew* que eu tinha perdido antes, e estava pronto para ir.
O site ficou no ar o tempo todo, sem tempo de inatividade.
Se isso foi necessário ou não, eu definitivamente sinto que meus dados estão um pouco mais seguros agora, e não estou me aproximando de algum desastre não anunciado no futuro.
Obrigado por me dar a direção certa para descobrir isso, @pfaffman!