I am working on a big PostgreSQL project which, unfortunately in production (3 milion records in a table with 90 columns) runs a query (a select/join with 2 conditions) in about 2 minutes.
Supposing there is nothing to optimise on my query, are there any settings I could modify to make it run faster? This is the configuration of the database, and I have no idea what suits my needs:
version PostgreSQL 8.4.4 on i686-pc-linux-gnu, compiled by GCC gcc (GCC) 4.1.2 20080704 (Red Hat 4.1.2-44), 32-bit
checkpoint_completion_target 0.9
checkpoint_segments 10
custom_variable_classes pg_stat_statements
effective_cache_size 1GB
lc_collate fr_FR.UTF-8
lc_ctype fr_FR.UTF-8
listen_addresses *
log_autovacuum_min_duration 0
log_line_prefix %t [%p]: [%l-1] user=%u,db=%d
log_min_duration_statement 30s
logging_collector on
maintenance_work_mem 128MB
max_connections 100
max_stack_depth 2MB
pg_stat_statements.max 1000
pg_stat_statements.save on
pg_stat_statements.track all
random_page_cost 1.5
server_encoding UTF8
shared_buffers 128MB
TimeZone Europe/Paris
track_functions pl
wal_buffers 1MB
work_mem 8MB
Query:
SELECT distinct
((Table_Commande_Historique.COD_STECIAL
|| ',' || Table_Commande_Historique.COD_MCIAL
|| ',' || Table_Commande_Historique.NUM_REC_CLI
|| ',' || Table_Commande_Historique.NUM_DNT_CLI
|| ',' || Table_Commande_Historique.NUM_DDE)) cle
FROM G1DDE2_DDE Table_Commande_Historique
inner join "K2VER2_VER" ver
on ( Table_Commande_Historique.NUM_REC_CLI
= (string_to_array(ver.num_cle,','))[3]::int
OR Table_Commande_Historique.NUM_DNT_CLI
= (string_to_array(ver.num_cle,','))[3]::int
OR ver.num_cle = (Table_Commande_Historique.COD_MCIAL
|| ',' || Table_Commande_Historique.NUM_REC_CLI)
OR ver.num_cle = (Table_Commande_Historique.COD_MCIAL
|| ',' || Table_Commande_Historique.NUM_DNT_CLI) );
Indexes:
CREATE INDEX idx_combo1
ON g1dde2_dde
USING btree
(((cod_mcial || ','::text) || num_rec_cli) );
CREATE INDEX idx_combo2
ON g1dde2_dde
USING btree
(((cod_mcial || ','::text) || num_dnt_cli) );
CREATE INDEX idx_dnt
ON g1dde2_dde
USING btree
(num_dnt_cli );
CREATE INDEX idx_rec
ON g1dde2_dde
USING btree
(num_rec_cli );
CREATE INDEX idx_k2ver3sb
ON "K2VER2_VER"
USING btree
(num_cle );
EXPLAIN:
"HashAggregate (cost=197.97..201.77 rows=69 width=29)"
" -> Nested Loop (cost=1.29..197.35 rows=248 width=29)"
" -> Seq Scan on "K2VER2_VER" ver (cost=0.00..2.58 rows=58 width=19)"
" -> Bitmap Heap Scan on g1dde2_dde table_commande_historique (cost=1.29..2.84 rows=5 width=29)"
" Recheck Cond: ((table_commande_historique.num_rec_cli = ((string_to_array((ver.num_cle)::text, ','::text))[3])::integer) OR (table_commande_historique.num_dnt_cli = ((string_to_array((ver.num_cle)::text, ','::text))[3])::integer) OR ((ver.num_cle)::text = (((table_commande_historique.cod_mcial)::text || ','::text) || (table_commande_historique.num_rec_cli)::text)) OR ((ver.num_cle)::text = (((table_commande_historique.cod_mcial)::text || ','::text) || (table_commande_historique.num_dnt_cli)::text)))"
" -> BitmapOr (cost=1.29..1.29 rows=5 width=0)"
" -> Bitmap Index Scan on idx_rec (cost=0.00..0.32 rows=2 width=0)"
" Index Cond: (table_commande_historique.num_rec_cli = ((string_to_array((ver.num_cle)::text, ','::text))[3])::integer)"
" -> Bitmap Index Scan on idx_dnt (cost=0.00..0.32 rows=1 width=0)"
" Index Cond: (table_commande_historique.num_dnt_cli = ((string_to_array((ver.num_cle)::text, ','::text))[3])::integer)"
" -> Bitmap Index Scan on idx_combo1 (cost=0.00..0.32 rows=1 width=0)"
" Index Cond: ((ver.num_cle)::text = (((table_commande_historique.cod_mcial)::text || ','::text) || (table_commande_historique.num_rec_cli)::text))"
" -> Bitmap Index Scan on idx_combo2 (cost=0.00..0.32 rows=1 width=0)"
" Index Cond: ((ver.num_cle)::text = (((table_commande_historique.cod_mcial)::text || ','::text) || (table_commande_historique.num_dnt_cli)::text))"