iotop shows kswapd0 at 99.99% with 0% DISK READ and DISK WRITE
You are approaching this from the wrong angle. Only after optimizing your SQL should you consider throwing more RAM/CPU/Disk (I/O bandwidth) at the problem -- and addressing the problem as you've identified it.
First ask Postgres to EXPLAIN
(or EXPLAIN ANALYZE
) how it is performing the query.
Optimize the ever-loving kittens out of that, and then if you still have performance problems investigate further to determine where the bottleneck is (sonassi gave you some good suggestions on stuff you should look at in addition to iotop
).
If you are running your web stack and DB on the same server, now is a good time to split them up as well...