I’m not sure if you’re interested in modifying the query, but from my few tests on localhost I’ve found using the badge_posts VIEW ran faster than using the posts table.
* it doesn’t show in the Data Explorer because it isn’t a table
CREATE VIEW badge_posts AS
SELECT p.id,
p.user_id,
p.topic_id,
p.post_number,
p.raw,
p.cooked,
p.created_at,
p.updated_at,
p.reply_to_post_number,
p.reply_count,
p.quote_count,
p.deleted_at,
p.off_topic_count,
p.like_count,
p.incoming_link_count,
p.bookmark_count,
p.avg_time,
p.score,
p.reads,
p.post_type,
p.vote_count,
p.sort_order,
p.last_editor_id,
p.hidden,
p.hidden_reason_id,
p.notify_moderators_count,
p.spam_count,
p.illegal_count,
p.inappropriate_count,
p.last_version_at,
p.user_deleted,
p.reply_to_user_id,
p.percent_rank,
p.notify_user_count,
p.like_score,
p.deleted_by_id,
p.edit_reason,
p.word_count,
p.version,
p.cook_method,
p.wiki,
p.baked_at,
p.baked_version,
p.hidden_at,
p.self_edits,
p.reply_quoted,
p.via_email,
p.raw_email,
p.public_version,
p.action_code
FROM ((posts p
JOIN topics t ON ((t.id = p.topic_id)))
JOIN categories c ON ((c.id = t.category_id)))
WHERE (((((c.allow_badges AND (p.deleted_at IS NULL)) AND (t.deleted_at IS NULL)) AND (NOT c.read_restricted)) AND t.visible) AND (p.post_type = ANY (ARRAY[1, 2, 3])));