Tenho 6GB de RAM no meu laptop e para teste estou criando uma tabela de 50mil linhas no PostgreSQL 9.3. Em seguida, quero criar um índice na tabela.
A tabela e o índice resultante juntos (ou o dobro do tamanho total da tabela) podem caber em 5 GB de RAM e eu defini maintenance_work_mem
5 GB, ainda CREATE INDEX
usa classificação externa com cerca de 1,4 GB de arquivos temporários. Por que?
Minha expectativa de que ele seja capaz de classificar na RAM não é razoável?
test=# set maintenance_work_mem to '5GB';
SET
test=# create table t1 as (select i::int, random() as f from generate_series(1, 50000000) i);
SELECT 50000000
test=# select pg_size_pretty(pg_relation_size('t1'));
pg_size_pretty
----------------
2111 MB
(1 row)
test=# create index on t1(f, i);
CREATE INDEX
test=# select pg_size_pretty(pg_relation_size('t1_f_i_idx'));
pg_size_pretty
----------------
1504 MB
(1 row)
No registro do servidor:
LOG: temporary file: path "base/pgsql_tmp/pgsql_tmp22623.1", size 1073741824
STATEMENT: create index on t1(f, i);
LOG: temporary file: path "base/pgsql_tmp/pgsql_tmp22623.2", size 327622656
LOG: external sort ended, 171065 disk blocks used: CPU 6.78s/268.73u sec elapsed 313.18 sec
Existe uma maneira de calcular CREATE INDEX
o requisito de memória antes de executá-lo?
Até a versão 9.3, a matriz de indireção usada para classificação tinha que caber em uma única alocação de memória de 1 GB. Isso criou um limite artificial no número de tuplas que podem ser classificadas na memória. Uma vez que esse limite foi atingido, ele teve que mudar para uma classificação de disco, mesmo que houvesse memória sobrando.
Essa restrição foi removida na versão 9.4.