Таблица

=> CREATE DATABASE bstore_interaction;
CREATE DATABASE
=> \c bstore_interaction
You are now connected to database "bstore_interaction" as user "student".
=> CREATE TABLE big AS
  SELECT gen.id FROM generate_series(1,1000000) gen(id);
SELECT 1000000

Чтобы избавиться от непредсказуемости, связанной с работой очистки, лучше выполнить ее заранее вручную:

=> VACUUM big;
VACUUM

Чтение по 1 строке

Циклов в SQL нет, но мы можем сгенерировать нужные команды средствами командного интерпретатора bash и подать на вход psql.

В начале открываем курсор, в конце закрываем курсор:

postgres$ echo 'BEGIN; DECLARE c CURSOR FOR SELECT * FROM big;' > /var/lib/postgresql/declare.sql
postgres$ echo 'CLOSE c; COMMIT;' > /var/lib/postgresql/close.sql

По одной строке 1000000 раз:

postgres$ (for i in {1..1000000}; do echo 'FETCH 1 c;'; done;) > /var/lib/postgresql/fetch_1.sql

Замеряем время (вывод psql игнорируем - миллион строк выводить на консоль бессмысленно и очень долго).

postgres$ cd /var/lib/postgresql; /usr/bin/time -f '%E' -o t cat declare.sql fetch_1.sql close.sql | psql -d bstore_interaction >/dev/null; cat t
0:35.97

Чтение по 10 строк

postgres$ (for i in {1..100000}; do echo 'FETCH 10 c;'; done;) > /var/lib/postgresql/fetch_10.sql
postgres$ cd /var/lib/postgresql; /usr/bin/time -f '%E' -o t cat declare.sql fetch_10.sql close.sql | psql -d bstore_interaction >/dev/null; cat t
0:04.70

Чтение по 100 строк

postgres$ (for i in {1..10000}; do echo 'FETCH 100 c;'; done;) > /var/lib/postgresql/fetch_100.sql
postgres$ cd /var/lib/postgresql; /usr/bin/time -f '%E' -o t cat declare.sql fetch_100.sql close.sql | psql -d bstore_interaction >/dev/null; cat t
0:00.95

Чтение по 1000 строк

postgres$ (for i in {1..1000}; do echo 'FETCH 1000 c;'; done;) > /var/lib/postgresql/fetch_1000.sql
postgres$ cd /var/lib/postgresql; /usr/bin/time -f '%E' -o t cat declare.sql fetch_1000.sql close.sql | psql -d bstore_interaction >/dev/null; cat t
0:00.00

Выводы