Eu preciso fazer uma junção interna de 25 milhões de linhas em 25 milhões de linhas. A caixa é um Alienware area 51, 4 núcleos 25GB de memória e drive SATA (disco sem sistema). Até agora, foram 22 horas. Eu fiz btree indexar a coluna ID (bigint) na qual a junção está sendo feita para ambas as tabelas. Alguma dica? Quanto tempo você acha que eu tenho que esperar?
EXPLAIN SELECT
public.products_by_location_mv.id,
public.products_by_location_mv."data_object.unique_id",
public.products_by_location_mv.location AS outline,
public.products_by_location_mv.elevation_ft,
public.products_by_location_mv."geo_product.geo_product_id" AS pid,
public.products_by_location_mv.cntry_name,
public.products_by_location_mv.product_name,
public.products_by_location_mv.product_type,
public.products_by_location_mv.product_producer,
public.products_by_location_mv.product_size,
public.products_by_location_mv.do_location,
public.products_by_location_mv.product_location,
public.obj4.uid AS oid,
public.obj4.size_bytes,
public.obj4.object_date,
public.obj4.description,
public.obj4.location AS path
INTO
public.inventory0
FROM
public.obj4
INNER JOIN
public.products_by_location_mv
ON
(
public.obj4.id = public.products_by_location_mv.id) ;
"Hash Join (cost=3825983.03..12908235.27 rows=24202368 width=1356)"
" Hash Cond: (products_by_location_mv.id = obj4.id)"
" -> Seq Scan on products_by_location_mv (cost=0.00..1457298.68 rows=24202368 width=721)"
" -> Hash (cost=1414691.68..1414691.68 rows=25507868 width=643)"
" -> Seq Scan on obj4 (cost=0.00..1414691.68 rows=25507868 width=643)"
Embora seja difícil para mim entender a motivação para esse tipo de consulta, você não pode esperar nenhum tipo de eficiência, pois os resultados da consulta não caberão na memória principal. Se você deseja que os resultados sejam armazenados de alguma forma, a única maneira de fazer isso é através do comando COPY ( http://www.postgresql.org/docs/9.2/static/sql-copy.html ). COPY tem a vantagem de que, uma vez que uma linha é recuperada da consulta, ela vai diretamente para o armazenamento secundário. Dessa forma, você realmente tem a chance de concluir a consulta após algumas horas. Então, se necessário, você pode usar COPY novamente para carregar esses resultados em outra tabela de banco de dados.
Como eu disse, é uma operação única (preciso fazer uma limpeza única de alguns grandes dados, e nunca é compatível como coisas nos dias do ACID).
Dito isso, experimentei com muito menos colunas e o desempenho é muito bom. 37 minutos. (um rápido VÁCUO também pode ter ajudado).
Veja abaixo: