powered by simpleCommunicator - 2.0.60     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Что можно "покрутить", чтобы быстрее выполнялся запрос?
5 сообщений из 5, страница 1 из 1
Что можно "покрутить", чтобы быстрее выполнялся запрос?
    #35045463
Alexey Koptenkov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Здраствуйте Уважаемые!

Изначально запрос отрабатывал за 2мин, после растановки FK - за 1мин. Чувствую, что не предел, но при большем количестве записей в таблице звонков при таком раскладе долго прийдется ждать, что посоветуете? Возможно ли таблицу звонков, держать всю в памяти, благо планка памяти не на настолько дорогой ресурс?

На данный момент в таблице calls(75000), areacodes(7000), networks(35), rates(2000) записей.

Или все таки не стоит заморачиваться и реализовать калькуляцию с помощью встроенных процедур?

CPU: AMD Athlon(tm) 64 X2 Dual Core Processor 3600+
RAM: DDRII 1GB 533Mhz
Debian 4.1 (2.6.18-5-486)
Postgres 8.1.9
HDD: WD 10000RPM

shared_buffers = 32768
temp_buffers = 4096
work_mem = 32768
maintenance_work_mem = 16384
max_stack_depth = 4096
effective_cache_size = 16384

Таблицы:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
CREATE TABLE calls
(
  id bigserial NOT NULL,
  callid character( 32 ),
  host inet NOT NULL,
  dst_number_in character varying( 24 ),
  dst_number_out character varying( 24 ),
  src_number_bill character varying( 24 ),
  dst_number_bill character varying( 24 ),
  src_ip inet,
  dst_ip inet,
  elapsed_time integer NOT NULL,
  setup_time timestamp with time zone NOT NULL,
  connect_time timestamp with time zone,
  disconnect_time timestamp with time zone,
  CONSTRAINT call_pk PRIMARY KEY (id)
)
WITHOUT OIDS;

CREATE TABLE areacodes
(
  id bigserial NOT NULL,
  mask character varying( 24 ),
  destinationid integer,
  todate date,
  CONSTRAINT areacodes_pk PRIMARY KEY (id),
  CONSTRAINT areacodes_fk1 FOREIGN KEY (destinationid)
      REFERENCES destinations (id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION
)
WITHOUT OIDS;

CREATE INDEX fki_areacodes_fk1
  ON areacodes
  USING btree
  (destinationid);

CREATE TABLE networks
(
  id bigserial NOT NULL,
  contractid integer NOT NULL,
  net inet NOT NULL,
  CONSTRAINT network_pk PRIMARY KEY (id),
  CONSTRAINT networks_fk1 FOREIGN KEY (contractid)
      REFERENCES contracts (id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION,
  CONSTRAINT networks_unq_idx1 UNIQUE (net)
)
WITHOUT OIDS;

CREATE INDEX fki_networks_fk1
  ON networks
  USING btree
  (contractid);

CREATE TABLE rates
(
  id bigserial NOT NULL,
  contractid integer NOT NULL,
  mask character varying( 20 ),
  price numeric( 7 , 5 ) NOT NULL DEFAULT  0 ,
  fromdate date NOT NULL,
  todate date,
  day_start integer NOT NULL DEFAULT  0 ,
  day_end integer NOT NULL DEFAULT  6 ,
  time_start integer NOT NULL DEFAULT  0 ,
  time_end integer NOT NULL DEFAULT  1440 ,
  CONSTRAINT rates_pk PRIMARY KEY (id),
  CONSTRAINT contracts_fk1 FOREIGN KEY (contractid)
      REFERENCES contracts (id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION,
  CONSTRAINT rates_unq_idx1 UNIQUE (mask, contractid, fromdate, todate)
)
WITHOUT OIDS;

CREATE INDEX fki_contracts_fk1
  ON rates
  USING btree
  (contractid);

Запрос:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
SELECT to_char(d.connect_time, 'yyyy-MON'::text) AS period, c.contractid, c.mask, c.price, c.fromdate, c.todate, sum(d.elapsed_time) AS duration
   FROM rates c
   RIGHT JOIN ( SELECT a.id, a.callid, b.contractid, a.connect_time, a.dst_number_bill, a.elapsed_time
           FROM calls a
      LEFT JOIN networks b ON b.net >>= a.src_ip) d ON c.id = (( SELECT e.id
      FROM rates e
     WHERE e.contractid = d.contractid AND d.connect_time >= e.fromdate AND (d.connect_time < e.todate OR e.todate IS NULL) AND d.dst_number_bill::text ~~ (e.mask::text || '%'::text)
     ORDER BY e.mask DESC
    LIMIT  1 ))
  GROUP BY c.contractid, to_char(d.connect_time, 'yyyy-MON'::text), c.mask, c.price, c.fromdate, c.todate;
План запроса:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
"GroupAggregate  (cost=34771406.75..34808977.99 rows=1073464 width=43) (actual time=58584.692..58682.392 rows=428 loops=1)"
"  ->  Sort  (cost=34771406.75..34774090.41 rows=1073464 width=43) (actual time=58581.694..58597.169 rows=74032 loops=1)"
"        Sort Key: c.contractid, to_char(a.connect_time, 'yyyy-MON'::text), c.mask, c.price, c.fromdate, c.todate"
"        ->  Merge Right Join  (cost=176890.10..34640315.42 rows=1073464 width=43) (actual time=55762.697..56011.846 rows=74032 loops=1)"
"              Merge Cond: ("outer".id = "inner"."?column5?")"
"              ->  Index Scan using rates_pk on rates c  (cost=0.00..54.35 rows=1733 width=39) (actual time=0.016..1.930 rows=1733 loops=1)"
"              ->  Sort  (cost=176890.10..179573.76 rows=1073464 width=31) (actual time=55762.625..55780.858 rows=74032 loops=1)"
"                    Sort Key: (subplan)"
"                    ->  Nested Loop Left Join  (cost=1.32..50919.52 rows=1073464 width=31) (actual time=0.207..55399.577 rows=74032 loops=1)"
"                          Join Filter: ("inner".net >>= "outer".src_ip)"
"                          ->  Seq Scan on calls a  (cost=0.00..2612.32 rows=74032 width=38) (actual time=0.003..81.470 rows=74032 loops=1)"
"                          ->  Materialize  (cost=1.32..1.61 rows=29 width=15) (actual time=0.000..0.008 rows=35 loops=74032)"
"                                ->  Seq Scan on networks b  (cost=0.00..1.29 rows=29 width=15) (actual time=0.003..0.038 rows=35 loops=1)"
"                          SubPlan"
"                            ->  Limit  (cost=32.03..32.04 rows=1 width=17) (actual time=0.722..0.722 rows=1 loops=74032)"
"                                  ->  Sort  (cost=32.03..32.04 rows=1 width=17) (actual time=0.721..0.721 rows=1 loops=74032)"
"                                        Sort Key: mask"
"                                        ->  Bitmap Heap Scan on rates e  (cost=4.21..32.02 rows=1 width=17) (actual time=0.413..0.716 rows=1 loops=74032)"
"                                              Recheck Cond: (contractid = $0)"
"                                              Filter: (($1 >= fromdate) AND (($1 < todate) OR (todate IS NULL)) AND (($2)::text ~~ ((mask)::text || '%'::text)))"
"                                              ->  Bitmap Index Scan on fki_contracts_fk1  (cost=0.00..4.21 rows=347 width=0) (actual time=0.078..0.078 rows=364 loops=74032)"
"                                                    Index Cond: (contractid = $0)"
"Total runtime: 58698.390 ms"
...
Рейтинг: 0 / 0
Что можно "покрутить", чтобы быстрее выполнялся запрос?
    #35045514
Oleg Bartunov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Времени нет разбираться в запросе, но сразу напишу, что сами по себе FK ускорить запрос
не могли - это индексы помогли. И второе - настройки у тебя просто девственные :)
В форуме уже много раз писали как выбирать параметры, поищи.

А потом займись запросом.
...
Рейтинг: 0 / 0
Что можно "покрутить", чтобы быстрее выполнялся запрос?
    #35045515
Oleg Bartunov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я бы еще индексы сделал по колонкам, которые ты в запросе сравниваешь.
Например:

Код: plaintext
1.
2.
3.
SELECT a.id, a.callid, b.contractid, a.connect_time, a.dst_number_bill, a.elapsed_time
           FROM calls a
      LEFT JOIN networks b ON b.net >>= a.src_ip

Здесь явно просятся индексы по networks.net и по calls.src_ip. Ну и план это показывает.
Вообще говоря, это основы. Дальше сам смотри.
...
Рейтинг: 0 / 0
Что можно "покрутить", чтобы быстрее выполнялся запрос?
    #35045525
Alexey Koptenkov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Спасибо посмотрю параметры.

А насчет индексов на networks.net (поставил unique index) но по плану вижу, что не всеравно seq scan.

по calls.src_ip, а здесь вообще стоит ли??? полюбому всю таблицу сканирует, если всю таблицу сканирует то ведь быстрее seq scan, чем по индексу искать затем запись, причем в итоге все прийдется и прочитать. Поставил, попробовал - но оптимизатор тоже не взял этот индекс..
...
Рейтинг: 0 / 0
Что можно "покрутить", чтобы быстрее выполнялся запрос?
    #35059604
LeXa NalBat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
попробуйте переформулировать условие
Код: plaintext
d.dst_number_bill::text ~~ (e.mask::text || '%'::text)
в виде
Код: plaintext
e.mask IN ( substr(d.dst_number_bill, 1 , 1 ), substr(d.dst_number_bill, 1 , 2 ),.. )
и постройте индексы по (mask) и (contractid,mask)

PS: хочется заменить вложенные запросы на одноуровневый джоин, но не уверен, получится ли
...
Рейтинг: 0 / 0
5 сообщений из 5, страница 1 из 1
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Что можно "покрутить", чтобы быстрее выполнялся запрос?
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]