Your statistics estimates are reasonable, and it's a pretty simple query plan. That in its self is part of the problem.
The (very) expensive node is the bitmap heap scan:
Bitmap Heap Scan on post (cost=1049.44..15307.18 rows=927 width=16) (actual time=63.520..17702.219 rows=849 loops=1)
Recheck Cond: (tsvall @@ to_tsquery('trialing'::text))
Filter: ((at IS NULL) AND (NOT hide) AND (datepublished >= '2012-05-04 00:00:00'::timestamp without time zone) AND (datepublished <= '2013-06-04 23:59:59'::timestamp without time zone))
See the big, complex filter clause? That's a bit odd, in that it means Pg isn't using any other indexes to satisfy these conditions.
Does reducing your random_page_cost
cause Pg to use any other indexes?
In a worst case, you might be able to use an explicit CTE to force Pg to do the other filters first, then apply the tsquery on the result. This would require a bit materialize, so it's not ideal, something like:
WITH prefiltered AS (
SELECT id, tsvall, datepublished
FROM Table
WHERE datepublished BETWEEN '2012-05-01 00:00:00' AND '2013-05-15 23:59:59'
AND hide = false
)
SELECT
FROM prefiltered
WHERE tsvall @@ to_tsquery('query')
ORDER BY datepublished DESC;
Alternately, as Denis so sensibly pointed out, try creating a composite btree-gist index like:
CREATE INDEX posts_blah ON posts USING gist(datepublished, tsvall) WHERE (hide = false);
... though the greater size of this index and its update cost may be a problem.