You need dynamic commands inside a function or anonymous code block.
do $$
declare
rec record;
begin
for rec in
select relnamespace::regnamespace as namespace, relname
from pg_index i
join pg_class c on c.oid = i.indexrelid
where not indisvalid
loop
execute format('drop index %s.%s', rec.namespace, rec.relname);
-- optionally:
-- raise notice '%', format('drop index %s.%s', rec.namespace, rec.relname);
end loop;
end $$;
Postgres automatically creates an index when creating or altering table constraints in CREATE TABLE
or ALTER TABLE
. Other than these, it never creates indexes on its own.
The most likely cause of invalid indexes is careless use of the CREATE [UNIQUE] INDEX CONCURRENTLY
command. When the command is executed in parallel transactions, there is a high probability of deadlocks, which cause the command to fail and leave an invalid index. When a unique index is created concurrently, the uniqueness violation may also lead to failure.
Concurrent indexing should be under the strict control of an administrator who is aware of these issues, especially when it is automatically performed on a regular basis.
Read more in the documentation.