Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Что можно "покрутить", чтобы быстрее выполнялся запрос? / 5 сообщений из 5, страница 1 из 1
04.01.2008, 22:41
    #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
05.01.2008, 00:11
    #35045514
Oleg Bartunov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Что можно "покрутить", чтобы быстрее выполнялся запрос?
Времени нет разбираться в запросе, но сразу напишу, что сами по себе FK ускорить запрос
не могли - это индексы помогли. И второе - настройки у тебя просто девственные :)
В форуме уже много раз писали как выбирать параметры, поищи.

А потом займись запросом.
...
Рейтинг: 0 / 0
05.01.2008, 00:17
    #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
05.01.2008, 00:41
    #35045525
Alexey Koptenkov
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Что можно "покрутить", чтобы быстрее выполнялся запрос?
Спасибо посмотрю параметры.

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

по calls.src_ip, а здесь вообще стоит ли??? полюбому всю таблицу сканирует, если всю таблицу сканирует то ведь быстрее seq scan, чем по индексу искать затем запись, причем в итоге все прийдется и прочитать. Поставил, попробовал - но оптимизатор тоже не взял этот индекс..
...
Рейтинг: 0 / 0
14.01.2008, 12:57
    #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
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Что можно "покрутить", чтобы быстрее выполнялся запрос? / 5 сообщений из 5, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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