PostgreSQL performance problem -> tuning

Поиск
Список
Период
Сортировка
От Yaroslav Mazurak
Тема PostgreSQL performance problem -> tuning
Дата
Msg-id 3F30AF9E.2080607@lviv.bank.gov.ua
обсуждение исходный текст
Ответы Re: PostgreSQL performance problem -> tuning  (Richard Huxton <dev@archonet.com>)
Re: PostgreSQL performance problem -> tuning  (Tom Lane <tgl@sss.pgh.pa.us>)
Список pgsql-performance
Hi All!


    I have installed PostgreSQL 7.3.2 on FreeBSD 4.7, running on PC with
CPU Pentium II 400MHz and 384Mb RAM.

    Problem is that SQL statement (see below) is running too long. With
current WHERE clause 'SUBSTR(2, 2) IN ('NL', 'NM') return 25 records.
With 1 record, SELECT time is about 50 minutes and takes approx. 120Mb
RAM. With 25 records SELECT takes about 600Mb of memory and ends after
about 10 hours with error: "Memory exhausted in AllocSetAlloc(32)".

    ***
    How can I speed up processing? Why query (IMHO not too complex)
executes so long? :(
    ***

    Information about configuration, data structures and table sizes see
below. Model picture attached.

    Current postgresql.conf settings (some) are:

=== Cut ===
max_connections = 8

shared_buffers = 8192
max_fsm_relations = 256
max_fsm_pages = 65536
max_locks_per_transaction = 16
wal_buffers = 256

sort_mem = 131072
vacuum_mem = 16384

checkpoint_segments = 4
checkpoint_timeout = 300
commit_delay = 32000
commit_siblings = 4
fsync = false

enable_seqscan = false

effective_cache_size = 65536
=== Cut ===

    SELECT statement is:

SELECT    showcalc('B00204', dd, r020, t071) AS s04
FROM    v_file02wide
WHERE    a011 = 3
    AND inrepdate(data)
    AND SUBSTR(ncks, 2, 2) IN ('NL', 'NM')
    AND r030 = 980;

    Query plan is:


                         QUERY PLAN



------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  Aggregate  (cost=174200202474.99..174200202474.99 rows=1 width=143)
    ->  Hash Join  (cost=174200199883.63..174200202474.89 rows=43 width=143)
          Hash Cond: ("outer".id_k041 = "inner".id_k041)
          ->  Hash Join  (cost=174200199880.57..174200202471.07 rows=43
width=139)
                Hash Cond: ("outer".id_r030 = "inner".id_r030)
                ->  Hash Join  (cost=174200199865.31..174200202410.31
rows=8992 width=135)
                      Hash Cond: ("outer".id_r020 = "inner".id_r020)
                      ->  Hash Join
(cost=174200199681.91..174200202069.55 rows=8992 width=124)
                            Hash Cond: ("outer".id_dd = "inner".id_dd)
                            ->  Merge Join
(cost=174200199676.04..174200201906.32 rows=8992 width=114)
                                  Merge Cond: ("outer".id_v = "inner".id_v)
                                  Join Filter: (("outer".data >= CASE
WHEN ("inner".dataa IS NOT NULL) THEN "inner".dataa WHEN ("outer".data
IS NOT NULL) THEN "outer".data ELSE NULL::date END) AND ("outer".data <=
CASE WHEN ("inner".datab IS NOT NULL) THEN "inner".datab WHEN
("outer".data IS NOT NULL) THEN "outer".data ELSE NULL::date END))
                                  ->  Sort  (cost=42528.39..42933.04
rows=161858 width=65)
                                        Sort Key: filexxr.id_v
                                        ->  Hash Join
(cost=636.25..28524.10 rows=161858 width=65)
                                              Hash Cond: ("outer".id_obl
= "inner".id_obl)
                                              ->  Hash Join
(cost=632.67..25687.99 rows=161858 width=61)
                                                    Hash Cond:
("outer".id_r = "inner".id_r)
                                                    ->  Index Scan using
index_file02_k041 on file02  (cost=0.00..18951.63 rows=816093 width=32)
                                                    ->  Hash
(cost=615.41..615.41 rows=6903 width=29)
                                                          ->  Index Scan
using index_filexxr_a011 on filexxr  (cost=0.00..615.41 rows=6903 width=29)
                                                                Index
Cond: (id_a011 = 3)
                                                                Filter:
inrepdate(data)
                                              ->  Hash  (cost=3.47..3.47
rows=43 width=4)
                                                    ->  Index Scan using
kod_obl_pkey on kod_obl obl  (cost=0.00..3.47 rows=43 width=4)
                                  ->  Sort
(cost=174200157147.65..174200157150.57 rows=1167 width=49)
                                        Sort Key: dov_tvbv.id_v
                                        ->  Merge Join
(cost=0.00..174200157088.20 rows=1167 width=49)
                                              Merge Cond:
("outer".id_bnk = "inner".id_bnk)
                                              ->  Index Scan using
dov_bank_pkey on dov_bank  (cost=0.00..290100261328.45 rows=1450 width=13)
                                                    Filter: (subplan)
                                                    SubPlan
                                                      ->  Materialize
(cost=100000090.02..100000090.02 rows=29 width=11)
                                                            ->  Seq Scan
on dov_bank  (cost=100000000.00..100000090.02 rows=29 width=11)

Filter: ((substr((box)::text, 2, 2) = 'NL'::text) OR
(substr((box)::text, 2, 2) = 'NM'::text))
                                              ->  Index Scan using
index_dov_tvbv_bnk on dov_tvbv  (cost=0.00..142.42 rows=2334 width=36)
                            ->  Hash  (cost=5.83..5.83 rows=16 width=10)
                                  ->  Index Scan using ek_pok_r_pkey on
ek_pok_r epr  (cost=0.00..5.83 rows=16 width=10)
                      ->  Hash  (cost=178.15..178.15 rows=2100 width=11)
                            ->  Index Scan using kl_r020_pkey on kl_r020
  (cost=0.00..178.15 rows=2100 width=11)
                ->  Hash  (cost=15.26..15.26 rows=1 width=4)
                      ->  Index Scan using kl_r030_pkey on kl_r030 r030
  (cost=0.00..15.26 rows=1 width=4)
                            Filter: ((r030)::text = '980'::text)
          ->  Hash  (cost=3.04..3.04 rows=4 width=4)
                ->  Index Scan using kl_k041_pkey on kl_k041
(cost=0.00..3.04 rows=4 width=4)
(45 rows)

    Function showcalc definition is:

CREATE OR REPLACE FUNCTION showcalc(VARCHAR(10), VARCHAR(2), VARCHAR(4),
NUMERIC(16)) RETURNS NUMERIC(16)
LANGUAGE SQL AS '
-- Parameters: code, dd, r020, t071
    SELECT COALESCE(
        (SELECT sc.koef * $4
            FROM showing AS s NATURAL JOIN showcomp AS sc
            WHERE s.kod LIKE $1
                AND NOT SUBSTR(acc_mask, 1, 1) LIKE ''[''
                AND SUBSTR(acc_mask, 1, 4) LIKE $3
                AND SUBSTR(acc_mask, 5, 1) LIKE SUBSTR($2, 1, 1)),
        (SELECT SUM(sc.koef * COALESCE(showcalc(SUBSTR(acc_mask, 2,
LENGTH(acc_mask) - 2), $2, $3, $4), 0))
            FROM showing AS s NATURAL JOIN showcomp AS sc
            WHERE s.kod LIKE $1
                AND SUBSTR(acc_mask, 1, 1) LIKE ''[''),
        0) AS showing;
';

    View v_file02wide is:

CREATE VIEW v_file02wide AS
SELECT id_a011 AS a011, data, obl.ko, obl.nazva AS oblast, b030,
banx.box AS ncks, banx.nazva AS bank,
    epr.dd, r020, r030, a3, r030.nazva AS valuta, k041,
    -- Sum equivalent in national currency
    t071 * get_kurs(id_r030, data) AS t070,
    t071
FROM v_file02 AS vf02
    JOIN kod_obl AS obl USING(id_obl)
    JOIN (dov_bank NATURAL JOIN dov_tvbv) AS banx
        ON banx.id_v = vf02.id_v
            AND data BETWEEN COALESCE(banx.dataa, data)
                AND COALESCE(banx.datab, data)
    JOIN ek_pok_r AS epr USING(id_dd)
    JOIN kl_r020 USING(id_r020)
    JOIN kl_r030 AS r030 USING(id_r030)
    JOIN kl_k041 USING(id_k041);

    Function inrepdate is:

CREATE OR REPLACE FUNCTION inrepdate(DATE) RETURNS BOOL
LANGUAGE SQL AS '
    -- Returns true if given date is in repdate
    SELECT (SELECT COUNT(*) FROM repdate
        WHERE $1 BETWEEN COALESCE(data1, CURRENT_DATE)
            AND COALESCE(data2, CURRENT_DATE))
        > 0;
';

    Table sizes (records)
    filexxr        34712
    file02        816589
    v_file02    816589
    kod_obl        43
    banx        2334
    ek_pok_r    16
    kl_r020        2100
    kl_r030        208
    kl_r041        4
    v_file02wide
    showing        2787
    showcomp    13646
    repdate        1

    Table has indexes almost for all selected fields.
    showcalc in this query selects and uses 195 rows.
    Total query size is 8066 records (COUNT(*) executes about 33 seconds
and uses 120Mb RAM).


With best regards
    Yaroslav Mazurak.

Вложения

В списке pgsql-performance по дате отправления:

Предыдущее
От: Hannu Krosing
Дата:
Сообщение: Re: How Many Inserts Per Transactions
Следующее
От: Richard Huxton
Дата:
Сообщение: Re: PostgreSQL performance problem -> tuning