По порядку:
Повторно запрос выполняется много быстрее.
Значит, вы с головой упёрлись в диск.
Вариант есть только один - ставить быстрый диск.
Вариант похуже, т.к. диск всё равно у вас останется медленный и если не на чтении, то на старте и на записи вы туда упрётесь очень хорошо - использовать больше памяти. Чтобы как можно данных было в памяти. Но при работе эти данные всё равно надо поднимать с медленных дисков, потому базу сначала придётся разогревать. Есть даже штатная утилитка pg_prewarm
В конфиге postgresql менял настройки только авторизации.
По дефолту там что-то несмешное вместо shared_buffers. 32 что ли мегабайта? И это на ключевую характеристику базы.
Увеличивать хотя бы до 20% от общего объёма памяти на машине.
В третьих, актуальный Postgresql довольно плохо умеет развесистый IN. И тому есть не совсем очевидное решение - переписать в join:
select count(*) from test JOIN (VALUES (1),...,(10000)) AS v(val) USING (val);
Такой вот hash join работает быстрее IN. На 10000 элементах получали 10мс против 380мс у IN.