powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / оптимизация запроса
57 сообщений из 57, показаны все 3 страниц
оптимизация запроса
    #38125813
Viacheslav_mihalich
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Доброго дня!

В целях быстродействия функции решил оптимизировать в ней запрос:
сменить медленные подзапросы на LEFT JOIN.

вот исходный запрос:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
SELECT cl."ID", 
(SELECT "O_T_IDS"."NAME" FROM "O_T_IDS" WHERE "O_T_IDS"."ID" = cl."O_T_ID"),
(SELECT "P_T_IDS"."NAME" FROM "P_T_IDS" WHERE "P_T_IDS"."ID" = cl."P_T_ID"),
(SELECT "D_IDS"."NAME" FROM "D_IDS" WHERE "D_IDS"."ID" = cl."D_ID"),
FROM cl 
WHERE cl."S_ID" = 1
AND cl."EXPIRATION_TIME" is NULL 
order by cl."ID" asc;



перешел на LEFT JOIN:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
SELECT cl."ID", "O_T_IDS"."NAME", "P_T_IDS"."NAME", "D_IDS"."NAME",
FROM cl 
LEFT JOIN "O_T_IDS" ON "O_T_IDS"."ID" = cl."O_T_ID"
LEFT JOIN "P_T_IDS" ON "P_T_IDS"."ID" = cl."P_T_ID"
LEFT JOIN "D_IDS" ON "D_IDS"."ID" = cl."D_ID"
WHERE cl."S_ID" = 1
AND cl."EXPIRATION_TIME" is NULL 
order by cl."ID" asc;



как и ожидалось, результат получаем одинаковый.
Далее для сравнения запустил выполнение обоих запросов в цикле на 10000 повторений.
Результат:

1-й запрос:

QUERY PLAN
Result (cost=0.00..0.26 rows=1 width=0) (actual time=752.993..834.105 rows=50000 loops=1)
Total runtime: 894.151 ms

2-й запрос:

QUERY PLAN
Result (cost=0.00..0.26 rows=1 width=0) (actual time=875.821..957.876 rows=50000 loops=1)
Total runtime: 1017.922 ms

чем же запрос с использованием LEFT JOIN лучше запроса с использованием подзапросов,
если он медленнее выполняется?
...
Рейтинг: 0 / 0
оптимизация запроса
    #38125831
/\/\/\/\/\/\/\
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Viacheslav_mihalich,

Потому что сильно напоминает анекдот: "Мне Рабинович в коридоре напел".

Приведите нормальный план запроса, чтобы были видны какие индексы используются и используются ли вообще.

"Как и ожидалось..." -- если Вы намекаете на то, что PostgreSQL не годится для оптимальных запросов, то специально для Вас ответ: "таки да".

Вы в обеих запросах используете одно и то же условие: cl.s_id = 1 AND cl.expiration_time IS NULL. Только в первом запросе дополнительные данные вытягиваются только из отобранных данных (то есть после фильтра), а во втором фильтр применяется уже после того, как туева хуча дополнительных данных присоединена к результатам запроса. Вот почему второй вариант хуже.

При этом совершенно не ясна судьба фильтрации: есть ли индекс по cl.s_id, применяется ли он (по соображениям селективности), может быть есть смысл применить условный фильтр.

Приведите нормальный план запроса.
Сразу можете привести долю записей с cl.s_id = 1 из общей массы, распределение по другим значениям. А так же в комбинации с cl.expitation_time. Это чтобы прикинуть возможности индекса.
...
Рейтинг: 0 / 0
оптимизация запроса
    #38125847
Viacheslav_mihalich
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ну, спасибо!
Сразу 2 удовольствия в одном:
и ответ и анекдот

для запроса:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
SELECT cl."ID",
"OWNER_TYPE_IDS"."NAME",
"PAYMENT_TYPE_IDS"."NAME",
"DISTRICT_IDS"."NAME"
FROM "CLINICS" cl 
LEFT JOIN "OWNER_TYPE_IDS" ON "OWNER_TYPE_IDS"."ID" = cl."OWNER_TYPE_ID"
LEFT JOIN "PAYMENT_TYPE_IDS" ON "PAYMENT_TYPE_IDS"."ID" = cl."PAYMENT_TYPE_ID"
LEFT JOIN "DISTRICT_IDS" ON "DISTRICT_IDS"."ID" = cl."DISTRICT_ID"
WHERE cl."SETTLEMENT_ID" = 1
AND cl."EXPIRATION_TIME" is NULL order by cl."ID" asc;



план:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
"QUERY PLAN"
"Sort  (cost=4.34..4.35 rows=1 width=318)"
"  Sort Key: cl.""ID"""
"  ->  Nested Loop Left Join  (cost=0.00..4.33 rows=1 width=318)"
"        Join Filter: (""PAYMENT_TYPE_IDS"".""ID"" = cl.""PAYMENT_TYPE_ID"")"
"        ->  Nested Loop Left Join  (cost=0.00..3.27 rows=1 width=240)"
"              Join Filter: (""DISTRICT_IDS"".""ID"" = cl.""DISTRICT_ID"")"
"              ->  Nested Loop Left Join  (cost=0.00..2.18 rows=1 width=98)"
"                    Join Filter: (""OWNER_TYPE_IDS"".""ID"" = cl.""OWNER_TYPE_ID"")"
"                    ->  Seq Scan on ""CLINICS"" cl  (cost=0.00..1.09 rows=1 width=20)"
"                          Filter: ((""EXPIRATION_TIME"" IS NULL) AND (""SETTLEMENT_ID"" = 1))"
"                    ->  Seq Scan on ""OWNER_TYPE_IDS""  (cost=0.00..1.04 rows=4 width=86)"
"              ->  Seq Scan on ""DISTRICT_IDS""  (cost=0.00..1.04 rows=4 width=150)"
"        ->  Seq Scan on ""PAYMENT_TYPE_IDS""  (cost=0.00..1.03 rows=3 width=86)"




для запроса:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
SELECT cl."ID", 
(SELECT "OWNER_TYPE_IDS"."NAME" FROM "OWNER_TYPE_IDS" WHERE "OWNER_TYPE_IDS"."ID" = cl."OWNER_TYPE_ID"),
(SELECT "PAYMENT_TYPE_IDS"."NAME" FROM "PAYMENT_TYPE_IDS" WHERE "PAYMENT_TYPE_IDS"."ID" = cl."PAYMENT_TYPE_ID"),
(SELECT "DISTRICT_IDS"."NAME" FROM "DISTRICT_IDS" WHERE "DISTRICT_IDS"."ID" = cl."DISTRICT_ID")
FROM "CLINICS" cl 
WHERE cl."SETTLEMENT_ID" = 1
AND cl."EXPIRATION_TIME" is NULL order by cl."ID" asc;



план:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
"QUERY PLAN"
"Sort  (cost=4.23..4.24 rows=1 width=20)"
"  Sort Key: cl.""ID"""
"  ->  Seq Scan on ""CLINICS"" cl  (cost=0.00..4.22 rows=1 width=20)"
"        Filter: ((""EXPIRATION_TIME"" IS NULL) AND (""SETTLEMENT_ID"" = 1))"
"        SubPlan 1"
"          ->  Seq Scan on ""OWNER_TYPE_IDS""  (cost=0.00..1.05 rows=1 width=82)"
"                Filter: (""ID"" = cl.""OWNER_TYPE_ID"")"
"        SubPlan 2"
"          ->  Seq Scan on ""PAYMENT_TYPE_IDS""  (cost=0.00..1.04 rows=1 width=82)"
"                Filter: (""ID"" = cl.""PAYMENT_TYPE_ID"")"
"        SubPlan 3"
"          ->  Seq Scan on ""DISTRICT_IDS""  (cost=0.00..1.05 rows=1 width=146)"
"                Filter: (""ID"" = cl.""DISTRICT_ID"")"
...
Рейтинг: 0 / 0
оптимизация запроса
    #38125852
/\/\/\/\/\/\/\
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Viacheslav_mihalich,

Так и есть!

Seq Scan on ""CLINICS"" cl (cost=0.00..1.09 rows=1 width=20)"
Filter: ((""EXPIRATION_TIME"" IS NULL) AND (""SETTLEMENT_ID"" = 1))"

В обеих запросах это не вызывает совершенно никаких эмоций. С учетом предыдущих предложений обратить внимание на построение индекса.

Вам на будущее: всегда приводите реальные запросы с которыми работаете. Потому что в 95% случаев выясняется, что запрос был другим, а вся беседа была зря.
...
Рейтинг: 0 / 0
оптимизация запроса
    #38126048
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Viacheslav_mihalich,

вы приводите
а)результаты explain analyze а не explain
б)На рабочих данных а не на пустой таблице (то что вы привели)

планы запросов ЗАВИСЯТ от данных в таблице и смотреть планы на пустых таблицах смысла ровно 0.

Если возращается 50000 строк в запросе то оба варианта будут небыстрыми...
...
Рейтинг: 0 / 0
оптимизация запроса
    #38126223
Viacheslav_mihalich
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Привожу с нагруженной таблицей в 100008 записей:
1.
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
explain analyze SELECT cl."ID",
"OWNER_TYPE_IDS"."NAME",
"PAYMENT_TYPE_IDS"."NAME",
"DISTRICT_IDS"."NAME"
FROM "CLINICS" cl 
LEFT JOIN "OWNER_TYPE_IDS" ON "OWNER_TYPE_IDS"."ID" = cl."OWNER_TYPE_ID"
LEFT JOIN "PAYMENT_TYPE_IDS" ON "PAYMENT_TYPE_IDS"."ID" = cl."PAYMENT_TYPE_ID"
LEFT JOIN "DISTRICT_IDS" ON "DISTRICT_IDS"."ID" = cl."DISTRICT_ID"
WHERE cl."SETTLEMENT_ID" = 1
AND cl."EXPIRATION_TIME" is NULL order by cl."ID" asc;



QUERY PLAN:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
"Nested Loop Left Join  (cost=0.00..13172.67 rows=50122 width=318) (actual time=0.072..2541.229 rows=50011 loops=1)"
"  Join Filter: ("DISTRICT_IDS"."ID" = cl."DISTRICT_ID")"
"  ->  Nested Loop Left Join  (cost=0.00..10164.30 rows=50122 width=176) (actual time=0.057..1684.598 rows=50011 loops=1)"
"        Join Filter: ("PAYMENT_TYPE_IDS"."ID" = cl."PAYMENT_TYPE_ID")"
"        ->  Nested Loop Left Join  (cost=0.00..7907.77 rows=50122 width=98) (actual time=0.034..955.021 rows=50011 loops=1)"
"              Join Filter: ("OWNER_TYPE_IDS"."ID" = cl."OWNER_TYPE_ID")"
"              ->  Index Scan using "CLINICS_pkey" on "CLINICS" cl  (cost=0.00..4899.40 rows=50122 width=20) (actual time=0.016..89.975 rows=50011 loops=1)"
"                    Filter: (("EXPIRATION_TIME" IS NULL) AND ("SETTLEMENT_ID" = 1))"
"              ->  Materialize  (cost=0.00..1.06 rows=4 width=86) (actual time=0.001..0.006 rows=4 loops=50011)"
"                    ->  Seq Scan on "OWNER_TYPE_IDS"  (cost=0.00..1.04 rows=4 width=86) (actual time=0.003..0.008 rows=4 loops=1)"
"        ->  Materialize  (cost=0.00..1.04 rows=3 width=86) (actual time=0.001..0.005 rows=3 loops=50011)"
"              ->  Seq Scan on "PAYMENT_TYPE_IDS"  (cost=0.00..1.03 rows=3 width=86) (actual time=0.002..0.006 rows=3 loops=1)"
"  ->  Materialize  (cost=0.00..1.06 rows=4 width=150) (actual time=0.001..0.006 rows=4 loops=50011)"
"        ->  Seq Scan on "DISTRICT_IDS"  (cost=0.00..1.04 rows=4 width=150) (actual time=0.002..0.008 rows=4 loops=1)"
"Total runtime: 2604.619 ms"



2.
Код: plsql
1.
2.
3.
4.
5.
6.
7.
explain analyze SELECT cl."ID", 
(SELECT "OWNER_TYPE_IDS"."NAME" FROM "OWNER_TYPE_IDS" WHERE "OWNER_TYPE_IDS"."ID" = cl."OWNER_TYPE_ID"),
(SELECT "PAYMENT_TYPE_IDS"."NAME" FROM "PAYMENT_TYPE_IDS" WHERE "PAYMENT_TYPE_IDS"."ID" = cl."PAYMENT_TYPE_ID"),
(SELECT "DISTRICT_IDS"."NAME" FROM "DISTRICT_IDS" WHERE "DISTRICT_IDS"."ID" = cl."DISTRICT_ID")
FROM "CLINICS" cl 
WHERE cl."SETTLEMENT_ID" = 1
AND cl."EXPIRATION_TIME" is NULL order by cl."ID" asc;



QUERY PLAN:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
"Index Scan using "CLINICS_pkey" on "CLINICS" cl  (cost=0.00..162157.18 rows=50122 width=20) (actual time=0.051..1586.286 rows=50011 loops=1)"
"  Filter: (("EXPIRATION_TIME" IS NULL) AND ("SETTLEMENT_ID" = 1))"
"  SubPlan 1"
"    ->  Seq Scan on "OWNER_TYPE_IDS"  (cost=0.00..1.05 rows=1 width=82) (actual time=0.002..0.004 rows=1 loops=50011)"
"          Filter: ("ID" = cl."OWNER_TYPE_ID")"
"  SubPlan 2"
"    ->  Seq Scan on "PAYMENT_TYPE_IDS"  (cost=0.00..1.04 rows=1 width=82) (actual time=0.002..0.004 rows=1 loops=50011)"
"          Filter: ("ID" = cl."PAYMENT_TYPE_ID")"
"  SubPlan 3"
"    ->  Seq Scan on "DISTRICT_IDS"  (cost=0.00..1.05 rows=1 width=146) (actual time=0.002..0.004 rows=1 loops=50011)"
"          Filter: ("ID" = cl."DISTRICT_ID")"
"Total runtime: 1651.062 ms"



сама таблица:

Код: plsql
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.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
CREATE TABLE "CLINICS"
(
  "ID" bigserial NOT NULL,
  "NAME" character varying(32),
  "NUMBER" integer, -- Number of the clinic, e.g. N35
  "STREET" character varying(64) NOT NULL,
  "SETTLEMENT_ID" integer NOT NULL,
  "IS_CHILDRENS" boolean,
  "IS_RECOVERY" boolean,
  "IS_DENTAL" boolean,
  "IS_NIGHT" boolean,
  "TELEPHONES" character varying(64),
  "WEBSITE" character varying(64),
  "OWNER_TYPE_ID" integer,
  "PAYMENT_TYPE_ID" integer,
  "DISTRICT_ID" integer,
  "EXPIRATION_TIME" timestamp without time zone,
  "HOUSE_NUM" integer NOT NULL,
  "HOUSING_NUM" integer,
  "IS_DIAGNOSTIC" boolean,
  "IS_CONSULTING" boolean,
  "INFO" character varying(2048),
  "IMAGE" character varying(64),
  CONSTRAINT "CLINICS_pkey" PRIMARY KEY ("ID" ),
  CONSTRAINT "DISTRICT_ID" FOREIGN KEY ("DISTRICT_ID")
      REFERENCES "DISTRICT_IDS" ("ID") MATCH SIMPLE
      ON UPDATE CASCADE ON DELETE CASCADE,
  CONSTRAINT "OWNER_TYPE_ID" FOREIGN KEY ("OWNER_TYPE_ID")
      REFERENCES "OWNER_TYPE_IDS" ("ID") MATCH SIMPLE
      ON UPDATE CASCADE ON DELETE RESTRICT,
  CONSTRAINT "PAYMENT_TYPE_ID" FOREIGN KEY ("PAYMENT_TYPE_ID")
      REFERENCES "PAYMENT_TYPE_IDS" ("ID") MATCH SIMPLE
      ON UPDATE CASCADE ON DELETE RESTRICT,
  CONSTRAINT "SETTLEMENT_ID" FOREIGN KEY ("SETTLEMENT_ID")
      REFERENCES "SETTLEMENTS" ("ID") MATCH SIMPLE
      ON UPDATE CASCADE ON DELETE RESTRICT,
  CONSTRAINT positive_distr_id CHECK ("DISTRICT_ID" > 0),
  CONSTRAINT positive_house_num CHECK ("HOUSE_NUM" > 0),
  CONSTRAINT positive_housing_num CHECK ("HOUSING_NUM" > 0),
  CONSTRAINT positive_number CHECK ("NUMBER" > 0),
  CONSTRAINT positive_owner_type_id CHECK ("OWNER_TYPE_ID" > 0),
  CONSTRAINT positive_payment_type_id CHECK ("PAYMENT_TYPE_ID" > 0),
  CONSTRAINT positive_set_id CHECK ("SETTLEMENT_ID" > 0)
)
WITH (
  OIDS=FALSE
);
ALTER TABLE "CLINICS"
  OWNER TO postgres;
COMMENT ON COLUMN "CLINICS"."NUMBER" IS 'Number of the clinic, e.g. N35';


-- Index: "fki_DISTRICT_ID"

-- DROP INDEX "fki_DISTRICT_ID";

CREATE INDEX "fki_DISTRICT_ID"
  ON "CLINICS"
  USING btree
  ("DISTRICT_ID" );

-- Index: "fki_OWNER_TYPE_ID"

-- DROP INDEX "fki_OWNER_TYPE_ID";

CREATE INDEX "fki_OWNER_TYPE_ID"
  ON "CLINICS"
  USING btree
  ("OWNER_TYPE_ID" );

-- Index: "fki_PAYMENT_TYPE_ID"

-- DROP INDEX "fki_PAYMENT_TYPE_ID";

CREATE INDEX "fki_PAYMENT_TYPE_ID"
  ON "CLINICS"
  USING btree
  ("PAYMENT_TYPE_ID" );

-- Index: "fki_SETTLEMENT_ID"

-- DROP INDEX "fki_SETTLEMENT_ID";

CREATE INDEX "fki_SETTLEMENT_ID"
  ON "CLINICS"
  USING btree
  ("SETTLEMENT_ID" );

-- Index: uniq_duplicate_record_name

-- DROP INDEX uniq_duplicate_record_name;

CREATE UNIQUE INDEX uniq_duplicate_record_name
  ON "CLINICS"
  USING btree
  ("NAME" COLLATE pg_catalog."default" , "STREET" COLLATE pg_catalog."default" , "SETTLEMENT_ID" , "HOUSE_NUM" )
  WHERE "EXPIRATION_TIME" IS NULL;

-- Index: uniq_duplicate_record_number

-- DROP INDEX uniq_duplicate_record_number;

CREATE UNIQUE INDEX uniq_duplicate_record_number
  ON "CLINICS"
  USING btree
  ("NUMBER" , "STREET" COLLATE pg_catalog."default" , "SETTLEMENT_ID" , "HOUSE_NUM" )
  WHERE "EXPIRATION_TIME" IS NULL;
...
Рейтинг: 0 / 0
оптимизация запроса
    #38126237
/\/\/\/\/\/\/\
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Viacheslav_mihalich,

Пожалуйста, приведите результат запросов:

Код: sql
1.
2.
3.
4.
5.
6.
SELECT
  settlement_id,
  COUNT(*)
FROM clinics
GROUP BY settlement_id
;



Код: sql
1.
2.
3.
4.
5.
6.
SELECT
  COUNT(*) AS cou,
  SUM(CASE WHEN settlement_id = 1 THEN 1 ELSE 0 END) AS cou_settlement_one,
  SUM(CASE WHEN (settlement_id = 1) AND (expitation_time IS NULL) THEN 1 ELSE 0 END) AS cou_
FROM clinics
;
...
Рейтинг: 0 / 0
оптимизация запроса
    #38126282
Viacheslav_mihalich
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
1.
Код: plsql
1.
2.
3.
4.
5.
SELECT
  "SETTLEMENT_ID",
  COUNT(*)
FROM "CLINICS"
GROUP BY "SETTLEMENT_ID";



результат:

Код: sql
1.
2.
3.
4.
SETTLEMENT_ID	   count
1	           50012
2	           49995
3	           1



2.
Код: plsql
1.
2.
3.
4.
5.
SELECT
  COUNT(*) AS cou,
  SUM(CASE WHEN "SETTLEMENT_ID" = 1 THEN 1 ELSE 0 END) AS cou_settlement_one,
  SUM(CASE WHEN ("SETTLEMENT_ID" = 1) AND ("EXPIRATION_TIME" IS NULL) THEN 1 ELSE 0 END) AS cou_
FROM "CLINICS";



результат:

Код: sql
1.
2.
cou	cou_settlement_one      cou_
100008	50012               	50011
...
Рейтинг: 0 / 0
оптимизация запроса
    #38126286
Viacheslav_mihalich
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
с "EXPIRATION_TIME" IS NULL маловато конечно данных,
по полю "SETTLEMENT_ID" данные отличаются.

Возможно такие данные не показательны,
могу по-разнообразней таблицу заполнить:
с множеством различных "SETTLEMENT_ID"
и чтобы "EXPIRATION_TIME" IS NULL было по-больше.
...
Рейтинг: 0 / 0
оптимизация запроса
    #38126289
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Viacheslav_mihalich,

пока у вас в присоединяемых таблицах по 1-2-5 записям план с subrequests вероятнее всего будет быстрее...

я бы попробовал поиграть с cpu_tuple_cost/random_page_cost для получения другого плана но принципиально быстрее не будет...
просто изза того что запрос на 50000 строк быстрым быть не может просто по своим свойствам...

попробуйте выполнить
set enable_material to 0;
и заново выполнить explain analyze запроса с left join
пришлите результаты они очень интересны будут...
вторым этапом попробовать еще сделать
set enable_nestloop to 0;
и тоже сделать explain analyze

если какая то из этих 2х версий будет заметно быстрее можно будет подумать о том в какую стороно крутить *_cost для получения более быстрого плана...
...
Рейтинг: 0 / 0
оптимизация запроса
    #38126331
Viacheslav_mihalich
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
выполнил set enable_material to 0;

затем заново выполнил explain analyze запроса с left join:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
"QUERY PLAN"
"Sort  (cost=24010.65..24135.96 rows=50122 width=318) (actual time=611.814..677.819 rows=50011 loops=1)"
"  Sort Key: cl.""ID"""
"  Sort Method: external sort  Disk: 5080kB"
"  ->  Hash Left Join  (cost=3.25..5362.84 rows=50122 width=318) (actual time=0.097..499.738 rows=50011 loops=1)"
"        Hash Cond: (cl.""DISTRICT_ID"" = ""DISTRICT_IDS"".""ID"")"
"        ->  Hash Left Join  (cost=2.16..4672.57 rows=50122 width=176) (actual time=0.068..360.714 rows=50011 loops=1)"
"              Hash Cond: (cl.""OWNER_TYPE_ID"" = ""OWNER_TYPE_IDS"".""ID"")"
"              ->  Hash Left Join  (cost=1.07..3982.33 rows=50122 width=98) (actual time=0.040..225.509 rows=50011 loops=1)"
"                    Hash Cond: (cl.""PAYMENT_TYPE_ID"" = ""PAYMENT_TYPE_IDS"".""ID"")"
"                    ->  Seq Scan on ""CLINICS"" cl  (cost=0.00..3292.10 rows=50122 width=20) (actual time=0.009..84.545 rows=50011 loops=1)"
"                          Filter: ((""EXPIRATION_TIME"" IS NULL) AND (""SETTLEMENT_ID"" = 1))"
"                    ->  Hash  (cost=1.03..1.03 rows=3 width=86) (actual time=0.018..0.018 rows=3 loops=1)"
"                          Buckets: 1024  Batches: 1  Memory Usage: 1kB"
"                          ->  Seq Scan on ""PAYMENT_TYPE_IDS""  (cost=0.00..1.03 rows=3 width=86) (actual time=0.003..0.008 rows=3 loops=1)"
"              ->  Hash  (cost=1.04..1.04 rows=4 width=86) (actual time=0.018..0.018 rows=4 loops=1)"
"                    Buckets: 1024  Batches: 1  Memory Usage: 1kB"
"                    ->  Seq Scan on ""OWNER_TYPE_IDS""  (cost=0.00..1.04 rows=4 width=86) (actual time=0.003..0.009 rows=4 loops=1)"
"        ->  Hash  (cost=1.04..1.04 rows=4 width=150) (actual time=0.018..0.018 rows=4 loops=1)"
"              Buckets: 1024  Batches: 1  Memory Usage: 1kB"
"              ->  Seq Scan on ""DISTRICT_IDS""  (cost=0.00..1.04 rows=4 width=150) (actual time=0.003..0.008 rows=4 loops=1)"
"Total runtime: 745.953 ms"



Шайтан!
время выполнения сократилось с 2604.619 ms до 745.953 ms!
А что собственно произошло после выполнения
set enable_material to 0;
в двух словах?

далее выполняю
set enable_nestloop to 0;
затем заново explain analyze запроса с left join:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
"Sort  (cost=24010.65..24135.96 rows=50122 width=318) (actual time=609.695..675.469 rows=50011 loops=1)"
"  Sort Key: cl."ID""
"  Sort Method: external sort  Disk: 5080kB"
"  ->  Hash Left Join  (cost=3.25..5362.84 rows=50122 width=318) (actual time=0.095..497.999 rows=50011 loops=1)"
"        Hash Cond: (cl."DISTRICT_ID" = "DISTRICT_IDS"."ID")"
"        ->  Hash Left Join  (cost=2.16..4672.57 rows=50122 width=176) (actual time=0.066..359.289 rows=50011 loops=1)"
"              Hash Cond: (cl."OWNER_TYPE_ID" = "OWNER_TYPE_IDS"."ID")"
"              ->  Hash Left Join  (cost=1.07..3982.33 rows=50122 width=98) (actual time=0.038..224.672 rows=50011 loops=1)"
"                    Hash Cond: (cl."PAYMENT_TYPE_ID" = "PAYMENT_TYPE_IDS"."ID")"
"                    ->  Seq Scan on "CLINICS" cl  (cost=0.00..3292.10 rows=50122 width=20) (actual time=0.009..84.043 rows=50011 loops=1)"
"                          Filter: (("EXPIRATION_TIME" IS NULL) AND ("SETTLEMENT_ID" = 1))"
"                    ->  Hash  (cost=1.03..1.03 rows=3 width=86) (actual time=0.017..0.017 rows=3 loops=1)"
"                          Buckets: 1024  Batches: 1  Memory Usage: 1kB"
"                          ->  Seq Scan on "PAYMENT_TYPE_IDS"  (cost=0.00..1.03 rows=3 width=86) (actual time=0.003..0.008 rows=3 loops=1)"
"              ->  Hash  (cost=1.04..1.04 rows=4 width=86) (actual time=0.018..0.018 rows=4 loops=1)"
"                    Buckets: 1024  Batches: 1  Memory Usage: 1kB"
"                    ->  Seq Scan on "OWNER_TYPE_IDS"  (cost=0.00..1.04 rows=4 width=86) (actual time=0.002..0.008 rows=4 loops=1)"
"        ->  Hash  (cost=1.04..1.04 rows=4 width=150) (actual time=0.018..0.018 rows=4 loops=1)"
"              Buckets: 1024  Batches: 1  Memory Usage: 1kB"
"              ->  Seq Scan on "DISTRICT_IDS"  (cost=0.00..1.04 rows=4 width=150) (actual time=0.003..0.008 rows=4 loops=1)"
"Total runtime: 742.405 ms"



время выполнения: "Total runtime: 748.315 ms".

P.S. Причем на время выполнение запроса с подзапросами эти магматические заклинания не подействовали:
было: 1651.062 ms, стало: 1646.203 ms.
...
Рейтинг: 0 / 0
оптимизация запроса
    #38126609
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Viacheslav_mihalichвыполнил set enable_material to 0;

затем заново выполнил explain analyze запроса с left join:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
"QUERY PLAN"
"Sort  (cost=24010.65..24135.96 rows=50122 width=318) (actual time=611.814..677.819 rows=50011 loops=1)"
"  Sort Key: cl.""ID"""
"  Sort Method: external sort  Disk: 5080kB"
"  ->  Hash Left Join  (cost=3.25..5362.84 rows=50122 width=318) (actual time=0.097..499.738 rows=50011 loops=1)"
"        Hash Cond: (cl.""DISTRICT_ID"" = ""DISTRICT_IDS"".""ID"")"
"        ->  Hash Left Join  (cost=2.16..4672.57 rows=50122 width=176) (actual time=0.068..360.714 rows=50011 loops=1)"
"              Hash Cond: (cl.""OWNER_TYPE_ID"" = ""OWNER_TYPE_IDS"".""ID"")"
"              ->  Hash Left Join  (cost=1.07..3982.33 rows=50122 width=98) (actual time=0.040..225.509 rows=50011 loops=1)"
"                    Hash Cond: (cl.""PAYMENT_TYPE_ID"" = ""PAYMENT_TYPE_IDS"".""ID"")"
"                    ->  Seq Scan on ""CLINICS"" cl  (cost=0.00..3292.10 rows=50122 width=20) (actual time=0.009..84.545 rows=50011 loops=1)"
"                          Filter: ((""EXPIRATION_TIME"" IS NULL) AND (""SETTLEMENT_ID"" = 1))"
"                    ->  Hash  (cost=1.03..1.03 rows=3 width=86) (actual time=0.018..0.018 rows=3 loops=1)"
"                          Buckets: 1024  Batches: 1  Memory Usage: 1kB"
"                          ->  Seq Scan on ""PAYMENT_TYPE_IDS""  (cost=0.00..1.03 rows=3 width=86) (actual time=0.003..0.008 rows=3 loops=1)"
"              ->  Hash  (cost=1.04..1.04 rows=4 width=86) (actual time=0.018..0.018 rows=4 loops=1)"
"                    Buckets: 1024  Batches: 1  Memory Usage: 1kB"
"                    ->  Seq Scan on ""OWNER_TYPE_IDS""  (cost=0.00..1.04 rows=4 width=86) (actual time=0.003..0.009 rows=4 loops=1)"
"        ->  Hash  (cost=1.04..1.04 rows=4 width=150) (actual time=0.018..0.018 rows=4 loops=1)"
"              Buckets: 1024  Batches: 1  Memory Usage: 1kB"
"              ->  Seq Scan on ""DISTRICT_IDS""  (cost=0.00..1.04 rows=4 width=150) (actual time=0.003..0.008 rows=4 loops=1)"
"Total runtime: 745.953 ms"



Шайтан!
время выполнения сократилось с 2604.619 ms до 745.953 ms!
А что собственно произошло после выполнения
set enable_material to 0;
в двух словах?

далее выполняю
set enable_nestloop to 0;
затем заново explain analyze запроса с left join:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
"Sort  (cost=24010.65..24135.96 rows=50122 width=318) (actual time=609.695..675.469 rows=50011 loops=1)"
"  Sort Key: cl."ID""
"  Sort Method: external sort  Disk: 5080kB"
"  ->  Hash Left Join  (cost=3.25..5362.84 rows=50122 width=318) (actual time=0.095..497.999 rows=50011 loops=1)"
"        Hash Cond: (cl."DISTRICT_ID" = "DISTRICT_IDS"."ID")"
"        ->  Hash Left Join  (cost=2.16..4672.57 rows=50122 width=176) (actual time=0.066..359.289 rows=50011 loops=1)"
"              Hash Cond: (cl."OWNER_TYPE_ID" = "OWNER_TYPE_IDS"."ID")"
"              ->  Hash Left Join  (cost=1.07..3982.33 rows=50122 width=98) (actual time=0.038..224.672 rows=50011 loops=1)"
"                    Hash Cond: (cl."PAYMENT_TYPE_ID" = "PAYMENT_TYPE_IDS"."ID")"
"                    ->  Seq Scan on "CLINICS" cl  (cost=0.00..3292.10 rows=50122 width=20) (actual time=0.009..84.043 rows=50011 loops=1)"
"                          Filter: (("EXPIRATION_TIME" IS NULL) AND ("SETTLEMENT_ID" = 1))"
"                    ->  Hash  (cost=1.03..1.03 rows=3 width=86) (actual time=0.017..0.017 rows=3 loops=1)"
"                          Buckets: 1024  Batches: 1  Memory Usage: 1kB"
"                          ->  Seq Scan on "PAYMENT_TYPE_IDS"  (cost=0.00..1.03 rows=3 width=86) (actual time=0.003..0.008 rows=3 loops=1)"
"              ->  Hash  (cost=1.04..1.04 rows=4 width=86) (actual time=0.018..0.018 rows=4 loops=1)"
"                    Buckets: 1024  Batches: 1  Memory Usage: 1kB"
"                    ->  Seq Scan on "OWNER_TYPE_IDS"  (cost=0.00..1.04 rows=4 width=86) (actual time=0.002..0.008 rows=4 loops=1)"
"        ->  Hash  (cost=1.04..1.04 rows=4 width=150) (actual time=0.018..0.018 rows=4 loops=1)"
"              Buckets: 1024  Batches: 1  Memory Usage: 1kB"
"              ->  Seq Scan on "DISTRICT_IDS"  (cost=0.00..1.04 rows=4 width=150) (actual time=0.003..0.008 rows=4 loops=1)"
"Total runtime: 742.405 ms"



время выполнения: "Total runtime: 748.315 ms".

P.S. Причем на время выполнение запроса с подзапросами эти магматические заклинания не подействовали:
было: 1651.062 ms, стало: 1646.203 ms.

а если вы еще set work_mem to '16Mb'; поставите еще быстрее будет (~500ms)
достаточно сочетания enable_material to 0 и повышенного work_mem

а что сделали - запретили использовать неудачный метод соединения таблиц для запроса... я потом поиграю с этим всем и попробую bug-report/test-case разработчикам отправить... не первый раз вижу когда план с материализацией тормозит... что то они с его ценой намудрили.
...
Рейтинг: 0 / 0
оптимизация запроса
    #38126735
Viacheslav_mihalich
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Maxim Boguk,

да, с set work_mem to '16Mb' еще быстрее отработало: "Total runtime: 687.393 ms"
В результате производительность возросла в 3,8 раза.

Видимо "set enable_material to 0;" и "set work_mem to '16Mb' " нужно выполнять каждый раз, как коннектишься к базе,
т.к. при выходе настройка слетает и все возвращается на круги своя.

А за помощь однозначно всем спасибо!
...
Рейтинг: 0 / 0
оптимизация запроса
    #38126761
/\/\/\/\/\/\/\/\/\
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Viacheslav_mihalich,

Эти параметры можно установить раз и навсегда в postgresql.conf (enable_material в разделе Planner Method Configuration).
(Может, там еще что-нибудь можно поднастроить).
...
Рейтинг: 0 / 0
оптимизация запроса
    #38126830
Viacheslav_mihalich
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Все здОрово: параметры выставил, на запрос с "explain analyze" полюбовался, порадовался скорости выполнения.
Но возник еще один, возможно глупый вопрос:
"explain analyze" снимаю, чтобы работать с реальными данными, и вижу, что настройки:
"set enable_material to 0;" и "set work_mem to '16Mb' " без "explain analyze" уже не действуют.
Для запроса:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
SELECT cl."ID",
"OWNER_TYPE_IDS"."NAME",
"PAYMENT_TYPE_IDS"."NAME",
"DISTRICT_IDS"."NAME"
FROM "CLINICS" cl 
LEFT JOIN "OWNER_TYPE_IDS" ON "OWNER_TYPE_IDS"."ID" = cl."OWNER_TYPE_ID"
LEFT JOIN "PAYMENT_TYPE_IDS" ON "PAYMENT_TYPE_IDS"."ID" = cl."PAYMENT_TYPE_ID"
LEFT JOIN "DISTRICT_IDS" ON "DISTRICT_IDS"."ID" = cl."DISTRICT_ID"
WHERE cl."SETTLEMENT_ID" = 1
AND cl."EXPIRATION_TIME" is NULL order by cl."ID" asc;


Суммарное время выполнения запроса: 5032 ms (он же с "explain analyze": 694.387 ms).


Для запроса:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
SELECT cl."ID", 
(SELECT "OWNER_TYPE_IDS"."NAME" FROM "OWNER_TYPE_IDS" WHERE "OWNER_TYPE_IDS"."ID" = cl."OWNER_TYPE_ID"),
(SELECT "PAYMENT_TYPE_IDS"."NAME" FROM "PAYMENT_TYPE_IDS" WHERE "PAYMENT_TYPE_IDS"."ID" = cl."PAYMENT_TYPE_ID"),
(SELECT "DISTRICT_IDS"."NAME" FROM "DISTRICT_IDS" WHERE "DISTRICT_IDS"."ID" = cl."DISTRICT_ID")
FROM "CLINICS" cl 
WHERE cl."SETTLEMENT_ID" = 1
AND cl."EXPIRATION_TIME" is NULL order by cl."ID" asc;


Суммарное время выполнения запроса: 4968 ms (он же с "explain analyze": 1642.155 ms).

P.S. других настроек не трогал, данные в таблице не менял.
...
Рейтинг: 0 / 0
оптимизация запроса
    #38126860
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Viacheslav_mihalich
чем же запрос с использованием LEFT JOIN лучше запроса с использованием подзапросов,
если он медленнее выполняется?


Время выполнения запроса не является критерием качества запроса, и, как ни странно, даже не является критерием производительности запроса.

Приводи io.

По сути же — что в лоб, что по лбу — запросы одинаковы, они даже возможно дают один и тот же план, и выполняются одинаковыми образом.
А то, что ты видишь— просто случайные отклонения, вызванные сторонними причинами.
...
Рейтинг: 0 / 0
оптимизация запроса
    #38126869
BLAHBLAHBLAH
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Viacheslav_mihalich,

либо в .config, либо
Код: plsql
1.
alter DATABASE BLAHBLAHBLAH set work_mem to '16Mb'


либо при старте каждого коннекта клиента
Код: plsql
1.
set work_mem to '16Mb'
...
Рейтинг: 0 / 0
оптимизация запроса
    #38126872
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
/\/\/\/\/\/\/\
Вы в обеих запросах используете одно и то же условие: cl.s_id = 1 AND cl.expiration_time IS NULL. Только в первом запросе дополнительные данные вытягиваются только из отобранных данных (то есть после фильтра), а во втором фильтр применяется уже после того, как туева хуча дополнительных данных присоединена к результатам запроса. Вот почему второй вариант хуже.




Предположения о порядке вычисления элементов запроса более чем смелые.

Для тех, кто не понимает сарказм, скажу прямо: они неверные.

Так же, как и оценки качества PG как субд.
...
Рейтинг: 0 / 0
оптимизация запроса
    #38126887
/\/\/\/\/\/\/\/\/\
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
MasterZivПредположения о порядке вычисления элементов запроса более чем смелые.


Пожалуйста, укажите где можно ознакомиться с порядком вычисления, чтобы предположения превратились в уверенность. Какой-нибудь RTFM, желательно официальный.
...
Рейтинг: 0 / 0
оптимизация запроса
    #38127153
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
/\/\/\/\/\/\/\/\/\MasterZivПредположения о порядке вычисления элементов запроса более чем смелые.


Пожалуйста, укажите где можно ознакомиться с порядком вычисления, чтобы предположения превратились в уверенность. Какой-нибудь RTFM, желательно официальный.

Нигде нельзя, порядка вычисления элементов запроса не существует. Порядок не определён.

Есть только один констрейнт -- условия в HAVING при наличии GROUP BY вычисляются после выполнения группировки (или по крайней мере в процессе её выполнения).
...
Рейтинг: 0 / 0
оптимизация запроса
    #38127170
/\/\/\/\/\/\/\/\/\
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
MasterZiv... порядка вычисления элементов запроса не существует. ...

Странно. "Жопа есть, а слова нет". Вычисления есть, а их порядка нет...
Значит Вы тоже не знаете. Жаль.
...
Рейтинг: 0 / 0
оптимизация запроса
    #38127315
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Viacheslav_mihalichВсе здОрово: параметры выставил, на запрос с "explain analyze" полюбовался, порадовался скорости выполнения.
Но возник еще один, возможно глупый вопрос:
"explain analyze" снимаю, чтобы работать с реальными данными, и вижу, что настройки:
"set enable_material to 0;" и "set work_mem to '16Mb' " без "explain analyze" уже не действуют.
Для запроса:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
SELECT cl."ID",
"OWNER_TYPE_IDS"."NAME",
"PAYMENT_TYPE_IDS"."NAME",
"DISTRICT_IDS"."NAME"
FROM "CLINICS" cl 
LEFT JOIN "OWNER_TYPE_IDS" ON "OWNER_TYPE_IDS"."ID" = cl."OWNER_TYPE_ID"
LEFT JOIN "PAYMENT_TYPE_IDS" ON "PAYMENT_TYPE_IDS"."ID" = cl."PAYMENT_TYPE_ID"
LEFT JOIN "DISTRICT_IDS" ON "DISTRICT_IDS"."ID" = cl."DISTRICT_ID"
WHERE cl."SETTLEMENT_ID" = 1
AND cl."EXPIRATION_TIME" is NULL order by cl."ID" asc;


Суммарное время выполнения запроса: 5032 ms (он же с "explain analyze": 694.387 ms).


Для запроса:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
SELECT cl."ID", 
(SELECT "OWNER_TYPE_IDS"."NAME" FROM "OWNER_TYPE_IDS" WHERE "OWNER_TYPE_IDS"."ID" = cl."OWNER_TYPE_ID"),
(SELECT "PAYMENT_TYPE_IDS"."NAME" FROM "PAYMENT_TYPE_IDS" WHERE "PAYMENT_TYPE_IDS"."ID" = cl."PAYMENT_TYPE_ID"),
(SELECT "DISTRICT_IDS"."NAME" FROM "DISTRICT_IDS" WHERE "DISTRICT_IDS"."ID" = cl."DISTRICT_ID")
FROM "CLINICS" cl 
WHERE cl."SETTLEMENT_ID" = 1
AND cl."EXPIRATION_TIME" is NULL order by cl."ID" asc;


Суммарное время выполнения запроса: 4968 ms (он же с "explain analyze": 1642.155 ms).

P.S. других настроек не трогал, данные в таблице не менял.

без explain analyze время выполнения запроса включает в себя
a)передачу ответа по сети
б)прием ответа клиентов

попробуйте с локального (для базы) хоста выполнить запрос...
и посмотреть на время...
50000 строк передать по сети вообще долгий процесс
...
Рейтинг: 0 / 0
оптимизация запроса
    #38128790
Viacheslav_mihalich
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Maxim Boguk,
все дело в том, что именно на localhost-е все это и наблюдается.
Т.е. передачи по сети не было.
...
Рейтинг: 0 / 0
оптимизация запроса
    #38128827
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Viacheslav_mihalichMaxim Boguk,
все дело в том, что именно на localhost-е все это и наблюдается.
Т.е. передачи по сети не было.

а сделайте

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
select count(*) from
(
SELECT cl."ID", 
(SELECT "O_T_IDS"."NAME" FROM "O_T_IDS" WHERE "O_T_IDS"."ID" = cl."O_T_ID"),
(SELECT "P_T_IDS"."NAME" FROM "P_T_IDS" WHERE "P_T_IDS"."ID" = cl."P_T_ID"),
(SELECT "D_IDS"."NAME" FROM "D_IDS" WHERE "D_IDS"."ID" = cl."D_ID"),
FROM cl 
WHERE cl."S_ID" = 1
AND cl."EXPIRATION_TIME" is NULL 
order by cl."ID" asc
offset 0
)
as t;



и
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
sekect count(*) from
(SELECT cl."ID", "O_T_IDS"."NAME", "P_T_IDS"."NAME", "D_IDS"."NAME",
FROM cl 
LEFT JOIN "O_T_IDS" ON "O_T_IDS"."ID" = cl."O_T_ID"
LEFT JOIN "P_T_IDS" ON "P_T_IDS"."ID" = cl."P_T_ID"
LEFT JOIN "D_IDS" ON "D_IDS"."ID" = cl."D_ID"
WHERE cl."S_ID" = 1
AND cl."EXPIRATION_TIME" is NULL 
order by cl."ID" asc
offset 0)
as t;



и пришлите какие времена у вас получились
(при work_mem 16Mb и set enable_material to 0;)
...
Рейтинг: 0 / 0
оптимизация запроса
    #38129007
Viacheslav_mihalich
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
При work_mem 16Mb и set enable_material to 0;

1.
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
select count(*) from
(
SELECT cl."ID", 
(SELECT "OWNER_TYPE_IDS"."NAME" FROM "OWNER_TYPE_IDS" WHERE "OWNER_TYPE_IDS"."ID" = cl."OWNER_TYPE_ID"),
(SELECT "PAYMENT_TYPE_IDS"."NAME" FROM "PAYMENT_TYPE_IDS" WHERE "PAYMENT_TYPE_IDS"."ID" = cl."PAYMENT_TYPE_ID"),
(SELECT "DISTRICT_IDS"."NAME" FROM "DISTRICT_IDS" WHERE "DISTRICT_IDS"."ID" = cl."DISTRICT_ID")
FROM "CLINICS" cl 
WHERE cl."SETTLEMENT_ID" = 1
AND cl."EXPIRATION_TIME" is NULL 
order by cl."ID" asc
offset 0
)
as t;



Суммарное время выполнения запроса: 375 ms.
1 строка получена.
count: 50011,

2.
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
SELECT count(*) from
(SELECT cl."ID", 
"OWNER_TYPE_IDS"."NAME",
"PAYMENT_TYPE_IDS"."NAME",
"DISTRICT_IDS"."NAME"
FROM "CLINICS" cl 
LEFT JOIN "OWNER_TYPE_IDS" ON "OWNER_TYPE_IDS"."ID" = cl."OWNER_TYPE_ID"
LEFT JOIN "PAYMENT_TYPE_IDS" ON "PAYMENT_TYPE_IDS"."ID" = cl."PAYMENT_TYPE_ID"
LEFT JOIN "DISTRICT_IDS" ON "DISTRICT_IDS"."ID" = cl."DISTRICT_ID"
WHERE cl."SETTLEMENT_ID" = 1
AND cl."EXPIRATION_TIME" is NULL 
order by cl."ID" asc
offset 0)
as t;



Суммарное время выполнения запроса: 78 ms.
1 строка получена.
count: 50011.
...
Рейтинг: 0 / 0
оптимизация запроса
    #38129026
Viacheslav_mihalich
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Такое подозрение, что сами запросы выполняются быстро,
а основное время идет на вывод 50000 записей на экран...
...
Рейтинг: 0 / 0
оптимизация запроса
    #38129909
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Viacheslav_mihalichТакое подозрение, что сами запросы выполняются быстро,
а основное время идет на вывод 50000 записей на экран...

это как раз часть:
б)прием ответа клиентов

(прием ответа отрисовка и тд)...

о которой я писал...
...
Рейтинг: 0 / 0
Период между сообщениями больше года.
оптимизация запроса
    #38931517
pcadviser
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
      sql := 'SELECT paths.seq, edges.* ' 
           ||'FROM '|| algo ||' (''SELECT * FROM (SELECT * FROM ' || addedges
           ||' UNION ALL SELECT * FROM ' || edges || ') AS graph '               
           ||'WHERE id NOT IN (SELECT gid FROM ' || deledges || ') '
           || 'AND source NOT IN (SELECT gid FROM ' || delnodes || ') '
           || 'AND target NOT IN (SELECT gid FROM ' || delnodes || ') '
           || CASE WHEN prohibited IS NOT NULL THEN
              'AND NOT st_intersects(the_geom, '
           || 'geomfromewkt('''||quote_literal(st_asewkt(prohibited))||''')) '
              ELSE '' END
           || CASE WHEN band IS NOT NULL THEN  
              'AND st_intersects(the_geom, '
           || 'geomfromewkt('''||quote_literal(st_asewkt(band))||''')) '
              ELSE '' END
           ||''', ' || source || ', ' || target
           ||', false, false) AS paths, '
           ||'(SELECT * FROM ' || addedges
           ||' UNION ALL SELECT * FROM ' || edges || ') AS edges '
           ||'WHERE paths.id2 = edges.id '
           ||'ORDER BY seq;';
...
Рейтинг: 0 / 0
оптимизация запроса
    #38931521
pcadviser
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
pcadviser
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
 
Помогите оптимизировать запрос :

      sql := 'SELECT paths.seq, edges.* ' 
           ||'FROM '|| algo ||' (''SELECT * FROM (SELECT * FROM ' || addedges
           ||' UNION ALL SELECT * FROM ' || edges || ') AS graph '               
           ||'WHERE id NOT IN (SELECT gid FROM ' || deledges || ') '
           || 'AND source NOT IN (SELECT gid FROM ' || delnodes || ') '
           || 'AND target NOT IN (SELECT gid FROM ' || delnodes || ') '
           || CASE WHEN prohibited IS NOT NULL THEN
              'AND NOT st_intersects(the_geom, '
           || 'geomfromewkt('''||quote_literal(st_asewkt(prohibited))||''')) '
              ELSE '' END
           || CASE WHEN band IS NOT NULL THEN  
              'AND st_intersects(the_geom, '
           || 'geomfromewkt('''||quote_literal(st_asewkt(band))||''')) '
              ELSE '' END
           ||''', ' || source || ', ' || target
           ||', false, false) AS paths, '
           ||'(SELECT * FROM ' || addedges
           ||' UNION ALL SELECT * FROM ' || edges || ') AS edges '
           ||'WHERE paths.id2 = edges.id '
           ||'ORDER BY seq;';
...
Рейтинг: 0 / 0
оптимизация запроса
    #38931938
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
pcadviserpcadviser
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
 
Помогите оптимизировать запрос :

      sql := 'SELECT paths.seq, edges.* ' 
           ||'FROM '|| algo ||' (''SELECT * FROM (SELECT * FROM ' || addedges
           ||' UNION ALL SELECT * FROM ' || edges || ') AS graph '               
           ||'WHERE id NOT IN (SELECT gid FROM ' || deledges || ') '
           || 'AND source NOT IN (SELECT gid FROM ' || delnodes || ') '
           || 'AND target NOT IN (SELECT gid FROM ' || delnodes || ') '
           || CASE WHEN prohibited IS NOT NULL THEN
              'AND NOT st_intersects(the_geom, '
           || 'geomfromewkt('''||quote_literal(st_asewkt(prohibited))||''')) '
              ELSE '' END
           || CASE WHEN band IS NOT NULL THEN  
              'AND st_intersects(the_geom, '
           || 'geomfromewkt('''||quote_literal(st_asewkt(band))||''')) '
              ELSE '' END
           ||''', ' || source || ', ' || target
           ||', false, false) AS paths, '
           ||'(SELECT * FROM ' || addedges
           ||' UNION ALL SELECT * FROM ' || edges || ') AS edges '
           ||'WHERE paths.id2 = edges.id '
           ||'ORDER BY seq;';



1)почему не в новой теме?
2)приведите результаты explain (analyze, costs, buffers, timing) ваш запрос; тогда и посмотрим.

PS: NOT IN использовать с подзапросом идея плохая в 90% случаев.

--Maxim Boguk
www.postgresql-consulting.ru
...
Рейтинг: 0 / 0
оптимизация запроса
    #38932933
pcadviser
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
1. на сайте недавно, не знал - что нужно в новой теме, учту

протестировал отдельно подзапрос с NOT IN - ми

Код: sql
1.
2.
3.
4.
5.
              SELECT * FROM (SELECT * FROM road_addedges 
              UNION ALL SELECT * FROM road.edges) AS graph WHERE 
              id NOT IN (SELECT gid FROM road_deledges) AND 
              source NOT IN (SELECT gid FROM road_delnodes) AND 
              target NOT IN (SELECT gid FROM road_delnodes)



Result (cost=120.00..905453.17 rows=1102808 width=494) (actual time=0.025..5114.715 rows=8822060 loops=1)

наверное можно переписать запрос через RIGHT OUTER JOIN ?
...
Рейтинг: 0 / 0
оптимизация запроса
    #38932936
pcadviser
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Maxim Bogukpcadviserпропущено...


1)почему не в новой теме?
2)приведите результаты explain (analyze, costs, buffers, timing) ваш запрос; тогда и посмотрим.

PS: NOT IN использовать с подзапросом идея плохая в 90% случаев.

--Maxim Boguk
www.postgresql-consulting.ru

1. на сайте недавно, не знал - что нужно в новой теме, учту

протестировал отдельно подзапрос с NOT IN - ми
Код: sql
1.
2.
3.
4.
5.
              SELECT * FROM (SELECT * FROM road_addedges 
              UNION ALL SELECT * FROM road.edges) AS graph WHERE 
              id NOT IN (SELECT gid FROM road_deledges) AND 
              source NOT IN (SELECT gid FROM road_delnodes) AND 
              target NOT IN (SELECT gid FROM road_delnodes)



Result (cost=120.00..905453.17 rows=1102808 width=494) (actual time=0.025..5114.715 rows=8822060 loops=1)

наверное можно переписать запрос через RIGHT OUTER JOIN ?
...
Рейтинг: 0 / 0
оптимизация запроса
    #38932980
Lonepsycho
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
pcadviser,

попробуйте

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
SELECT * 
FROM 
(
  SELECT * 
  FROM road_addedges 
  UNION ALL 
  SELECT * 
  FROM road.edges
) AS graph 
LEFT JOIN
road_deledges AS rd
ON graph.id = rd.gid
LEFT JOIN
road_delnodes AS rdns
ON source = rdns.gid
LEFT JOIN
road_delnodes AS rdnt
ON target = rdnt.gid
WHERE 
  rd.gid IS NULL AND
  rdns.gid IS NULL AND
  rdnt.gid IS NULL
...
Рейтинг: 0 / 0
оптимизация запроса
    #38932987
Lonepsycho
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
pcadviser,

или так:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
SELECT * 
FROM 
(
  SELECT * 
  FROM road_addedges 
  UNION ALL 
  SELECT * 
  FROM road.edges
) AS graph
WHERE 
NOT EXISTS (
  SELECT 1 FROM road_deledges AS rd WHERE rd.gid = graph.id
) AND
NOT EXISTS (
  SELECT 1 FROM road_delnodes AS rdn WHERE rdn.gid = graph.source
) AND
NOT EXISTS (
  SELECT 1 FROM road_delnodes AS rdn WHERE rdn.gid = graph.target
)
...
Рейтинг: 0 / 0
оптимизация запроса
    #38932989
Lonepsycho
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
pcadviser,

и да, Махим вас просил:

Maxim Boguk 2)приведите результаты explain (analyze, costs, buffers, timing) ваш запрос; тогда и посмотрим.
...
Рейтинг: 0 / 0
оптимизация запроса
    #38933049
qwwq
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
там не суть важно, как это фильтровать по этому условию
думаю, основная мякотка -- в наличии/отсутствии gist индексов по геометриям.
(не тащат же они 8 лямов записей из запроса )


2ТС: лениво раскрывать динамику -- приведите конечный текст запроса (а не строку сборки) в одном из вариантов параметров
желательно -- нормально отформатированную.
и вообще -- там у вас видится вызов динамики вложенный ['(''SELECT ...], что забавно.
...
Рейтинг: 0 / 0
оптимизация запроса
    #38933128
pcadviser
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
qwwqтам не суть важно, как это фильтровать по этому условию
думаю, основная мякотка -- в наличии/отсутствии gist индексов по геометриям.
(не тащат же они 8 лямов записей из запроса )


2ТС: лениво раскрывать динамику -- приведите конечный текст запроса (а не строку сборки) в одном из вариантов параметров
желательно -- нормально отформатированную.
и вообще -- там у вас видится вызов динамики вложенный ['(''SELECT ...], что забавно.

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
explain (analyze, costs, buffers) 
SELECT paths.seq, edges.* 
FROM pgr_astar ('SELECT * FROM (SELECT * FROM road_addedges UNION ALL SELECT * FROM road.edges) AS graph 
WHERE id NOT IN (SELECT gid FROM road_deledges) 
AND source NOT IN (SELECT gid FROM road_delnodes) 
AND target NOT IN (SELECT gid FROM road_delnodes) 
AND NOT st_intersects(the_geom, geomfromewkt(''SRID=4326;POLYGON((53 52,51 56,55 56,53 52))'')) ', 7000528, 7000530, false, false) AS paths, 
(SELECT * FROM road_addedges UNION ALL SELECT * FROM road.edges) AS edges 
WHERE paths.id2 = edges.id
ORDER BY seq;



результат :

Sort (cost=15564684.21..15674965.05 rows=44112335 width=498) (actual time=26819.681..26820.040 rows=6663 loops=1)
Sort Key: paths.seq
Sort Method: quicksort Memory: 2678kB
Buffers: shared hit=49986 read=728492, local hit=6671
-> Nested Loop (cost=0.00..12468.32 rows=44112335 width=498) (actual time=26790.620..26816.858 rows=6663 loops=1)
Join Filter: (paths.id2 = road_addedges.id)
Buffers: shared hit=49986 read=728492, local hit=6671
-> Function Scan on pgr_astar paths (cost=0.00..10.00 rows=1000 width=8) (actual time=26790.595..26791.357 rows=6664 loops=1)
Buffers: shared hit=23267 read=728492, local hit=3
Buffers: shared hit=26719, local hit=6668
-> Index Scan using edges_gid_idx on road_addedges (cost=0.00..0.32 rows=1 width=152) (actual time=0.000..0.000 rows=0 loops=6664)
Index Cond: (road_addedges.id = paths.id2)
Buffers: local hit=6668
-> Index Scan using edges_gid_idx on edges (cost=0.00..12.12 rows=1 width=494) (actual time=0.003..0.003 rows=1 loops=6664)
Index Cond: (road.edges.id = paths.id2)
Buffers: shared hit=26719
Total runtime: 26820.381 ms
...
Рейтинг: 0 / 0
оптимизация запроса
    #38933134
pcadviser
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
qwwq,

пропустил строчку

Append (cost=0.00..12.43 rows=2 width=323) (actual time=0.003..0.003 rows=1 loops=6664)
...
Рейтинг: 0 / 0
оптимизация запроса
    #38933137
pcadviser
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Lonepsycho,

результаты выше
...
Рейтинг: 0 / 0
оптимизация запроса
    #38933138
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
pcadviser,

у вас все время ожидаемо уходит на вызов функции pgr_astar
теперь берем все запросы внутри этой функции и поштучно анализируем что именно тормозит.

PS: из того что я вижу скорее всего тормозит диск и базе надо больше памяти чтобы она нормально там размещалась. Включить track_io_timing и прогоните еще раз тот же explain analyze.

PPS: когда я вижу куски SQL передаваемые параметрами в хранимку я уже могу предсказать что там все будет криво (так как так делать не надо никогда это исключительно кривой дизайн).

--Maxim Boguk
www.postgresql-consulting.ru
...
Рейтинг: 0 / 0
оптимизация запроса
    #38933151
pcadviser
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Maxim Bogukpcadviser,

у вас все время ожидаемо уходит на вызов функции pgr_astar
теперь берем все запросы внутри этой функции и поштучно анализируем что именно тормозит.

PS: из того что я вижу скорее всего тормозит диск и базе надо больше памяти чтобы она нормально там размещалась. Включить track_io_timing и прогоните еще раз тот же explain analyze.

PPS: когда я вижу куски SQL передаваемые параметрами в хранимку я уже могу предсказать что там все будет криво (так как так делать не надо никогда это исключительно кривой дизайн).

--Maxim Boguk
www.postgresql-consulting.ru

Включить track_io_timing нет возможности, так как версия postgres - 9.0
...
Рейтинг: 0 / 0
оптимизация запроса
    #38933157
pcadviser
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
PPS: когда я вижу куски SQL передаваемые параметрами в хранимку я уже могу предсказать что там все будет криво (так как так делать не надо никогда это исключительно кривой дизай

хранимая процедура реализована на PL/SQL C++.
набор данных передать в функцию иначе нельзя.
...
Рейтинг: 0 / 0
оптимизация запроса
    #38933167
pcadviser
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Lonepsychopcadviser,

или так:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
SELECT * 
FROM 
(
  SELECT * 
  FROM road_addedges 
  UNION ALL 
  SELECT * 
  FROM road.edges
) AS graph
WHERE 
NOT EXISTS (
  SELECT 1 FROM road_deledges AS rd WHERE rd.gid = graph.id
) AND
NOT EXISTS (
  SELECT 1 FROM road_delnodes AS rdn WHERE rdn.gid = graph.source
) AND
NOT EXISTS (
  SELECT 1 FROM road_delnodes AS rdn WHERE rdn.gid = graph.target
)



вот результат

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
explain (ANALYZE, costs, buffers) 
SELECT paths.seq, edges.* FROM pgr_astar ('SELECT * FROM (SELECT * FROM road_addedges UNION ALL
SELECT * FROM road.edges) AS graph 
WHERE NOT EXISTS (SELECT 1 FROM road_deledges AS rd WHERE rd.gid = graph.id) 
AND NOT EXISTS ( SELECT 1 FROM road_delnodes AS rdn WHERE rdn.gid = graph.source) 
AND NOT EXISTS ( SELECT 1 FROM road_delnodes AS rdn WHERE rdn.gid = graph.target) 
AND NOT st_intersects(the_geom, geomfromewkt(''SRID=4326;POLYGON((53 52,51 56,55 56,53 52))'')) ',
7000528, 7000530, false, false) AS paths, (SELECT * FROM road_addedges UNION ALL SELECT * FROM road.edges) AS edges 
WHERE paths.id2 = edges.id 
ORDER BY seq;



результат - время возрасло

Sort (cost=15564684.21..15674965.05 rows=44112335 width=498) (actual time=30923.256..30923.603 rows=6663 loops=1)
Sort Key: paths.seq
Sort Method: quicksort Memory: 2678kB
Buffers: shared hit=50018 read=728460, local hit=6670
-> Nested Loop (cost=0.00..12468.32 rows=44112335 width=498) (actual time=30894.333..30920.352 rows=6663 loops=1)
Join Filter: (paths.id2 = road_addedges.id)
Buffers: shared hit=50018 read=728460, local hit=6670
-> Function Scan on pgr_astar paths (cost=0.00..10.00 rows=1000 width=8) (actual time=30894.308..30894.946 rows=6664 loops=1)
Buffers: shared hit=23299 read=728460, local hit=2
-> Append (cost=0.00..12.43 rows=2 width=323) (actual time=0.003..0.003 rows=1 loops=6664)
Buffers: shared hit=26719, local hit=6668
-> Index Scan using edges_gid_idx on road_addedges (cost=0.00..0.32 rows=1 width=152) (actual time=0.000..0.000 rows=0 loops=6664)
Index Cond: (road_addedges.id = paths.id2)
Buffers: local hit=6668
-> Index Scan using edges_gid_idx on edges (cost=0.00..12.12 rows=1 width=494) (actual time=0.003..0.003 rows=1 loops=6664)
Index Cond: (road.edges.id = paths.id2)
Buffers: shared hit=26719
Total runtime: 30923.946 ms
...
Рейтинг: 0 / 0
оптимизация запроса
    #38933181
pcadviser
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Lonepsychopcadviser,

попробуйте

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
SELECT * 
FROM 
(
  SELECT * 
  FROM road_addedges 
  UNION ALL 
  SELECT * 
  FROM road.edges
) AS graph 
LEFT JOIN
road_deledges AS rd
ON graph.id = rd.gid
LEFT JOIN
road_delnodes AS rdns
ON source = rdns.gid
LEFT JOIN
road_delnodes AS rdnt
ON target = rdnt.gid
WHERE 
  rd.gid IS NULL AND
  rdns.gid IS NULL AND
  rdnt.gid IS NULL



Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
explain (ANALYZE, costs, buffers) 
SELECT paths.seq, edges.* FROM pgr_astar ('SELECT * FROM (SELECT * FROM road_addedges UNION ALL SELECT * FROM road.edges) AS graph 
LEFT JOIN road_deledges AS rd ON graph.id = rd.gid 
LEFT JOIN road_delnodes AS rdns ON graph.source = rdns.gid 
LEFT JOIN road_delnodes AS rdnt ON graph.target = rdnt.gid 
WHERE  rd.gid IS NULL AND rdns.gid IS NULL AND rdnt.gid IS NULL AND 
NOT st_intersects(the_geom, geomfromewkt(''SRID=4326;POLYGON((53 52,51 56,55 56,53 52))'')) ',
7000528, 7000530, false, false) AS paths,
(SELECT * FROM road_addedges UNION ALL SELECT * FROM road.edges) AS edges
WHERE paths.id2 = edges.id 
ORDER BY seq;



результат - время тоже увеличилось

Sort (cost=15564684.21..15674965.05 rows=44112335 width=498) (actual time=31767.105..31767.519 rows=6663 loops=1)
Sort Key: paths.seq
Sort Method: quicksort Memory: 2678kB
Buffers: shared hit=50103 read=728364, local hit=6670
-> Nested Loop (cost=0.00..12468.32 rows=44112335 width=498) (actual time=31736.068..31763.964 rows=6663 loops=1)
Join Filter: (paths.id2 = road_addedges.id)
Buffers: shared hit=50103 read=728364, local hit=6670
-> Function Scan on pgr_astar paths (cost=0.00..10.00 rows=1000 width=8) (actual time=31736.042..31736.635 rows=6664 loops=1)
Buffers: shared hit=23384 read=728364, local hit=2
-> Append (cost=0.00..12.43 rows=2 width=323) (actual time=0.003..0.003 rows=1 loops=6664)
Buffers: shared hit=26719, local hit=6668
-> Index Scan using edges_gid_idx on road_addedges (cost=0.00..0.32 rows=1 width=152) (actual time=0.000..0.000 rows=0 loops=6664)
Index Cond: (road_addedges.id = paths.id2)
Buffers: local hit=6668
-> Index Scan using edges_gid_idx on edges (cost=0.00..12.12 rows=1 width=494) (actual time=0.003..0.003 rows=1 loops=6664)
Index Cond: (road.edges.id = paths.id2)
Buffers: shared hit=26719

Total runtime: 31767.863 ms
...
Рейтинг: 0 / 0
оптимизация запроса
    #38933192
qwwq
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
из общих соображений -- вы туда через sql передаёте его возврат
т.е. оно там, унутре, исполняется "как есть"
а потом над возвратом измывается сишным кодом.

т.е. дайте план вот такого:

Код: sql
1.
2.
3.
4.
5.
6.
SELECT * FROM (SELECT * FROM road_addedges UNION ALL
SELECT * FROM road.edges) AS graph 
WHERE NOT EXISTS (SELECT 1 FROM road_deledges AS rd WHERE rd.gid = graph.id) 
AND NOT EXISTS ( SELECT 1 FROM road_delnodes AS rdn WHERE rdn.gid = graph.source) 
AND NOT EXISTS ( SELECT 1 FROM road_delnodes AS rdn WHERE rdn.gid = graph.target) 
AND NOT st_intersects(the_geom, geomfromewkt('SRID=4326;POLYGON((53 52,51 56,55 56,53 52))')) 


есть ли gist индексы по the_geom ?
...
Рейтинг: 0 / 0
оптимизация запроса
    #38933200
pcadviser
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
qwwqиз общих соображений -- вы туда через sql передаёте его возврат
т.е. оно там, унутре, исполняется "как есть"
а потом над возвратом измывается сишным кодом.

т.е. дайте план вот такого:

Код: sql
1.
2.
3.
4.
5.
6.
SELECT * FROM (SELECT * FROM road_addedges UNION ALL
SELECT * FROM road.edges) AS graph 
WHERE NOT EXISTS (SELECT 1 FROM road_deledges AS rd WHERE rd.gid = graph.id) 
AND NOT EXISTS ( SELECT 1 FROM road_delnodes AS rdn WHERE rdn.gid = graph.source) 
AND NOT EXISTS ( SELECT 1 FROM road_delnodes AS rdn WHERE rdn.gid = graph.target) 
AND NOT st_intersects(the_geom, geomfromewkt('SRID=4326;POLYGON((53 52,51 56,55 56,53 52))')) 



есть ли gist индексы по the_geom ?

индексы есть и по the_geom, id, gid, source, target

с применением NOT EXISTS, тоже пробывал
результат - хуже

результат - в теме, чуть выше
...
Рейтинг: 0 / 0
оптимизация запроса
    #38933205
qwwq
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
pcadviserqwwqиз общих соображений -- вы туда через sql передаёте его возврат
т.е. оно там, унутре, исполняется "как есть"
а потом над возвратом измывается сишным кодом.

т.е. дайте план вот такого:

Код: sql
1.
2.
3.
4.
5.
6.
SELECT * FROM (SELECT * FROM road_addedges UNION ALL
SELECT * FROM road.edges) AS graph 
WHERE NOT EXISTS (SELECT 1 FROM road_deledges AS rd WHERE rd.gid = graph.id) 
AND NOT EXISTS ( SELECT 1 FROM road_delnodes AS rdn WHERE rdn.gid = graph.source) 
AND NOT EXISTS ( SELECT 1 FROM road_delnodes AS rdn WHERE rdn.gid = graph.target) 
AND NOT st_intersects(the_geom, geomfromewkt('SRID=4326;POLYGON((53 52,51 56,55 56,53 52))')) 



есть ли gist индексы по the_geom ?

индексы есть и по the_geom, id, gid, source, target

с применением NOT EXISTS, тоже пробывал
результат - хуже

результат - в теме, чуть выше
гне надо пробЫвать, пробудете так всё на свете

надо сделать что просят, если лень читать
-- я вытащил наружу передаваемую в C динамику -- и прошу план по ней, а не по внешнему запросу
...
Рейтинг: 0 / 0
оптимизация запроса
    #38933207
qwwq
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
да, и втащите WHERE руками в части UNION ALL-а -- оно конечно планер должен это уметь, но писать изначально верно -- не повредит.
...
Рейтинг: 0 / 0
оптимизация запроса
    #38933208
qwwq
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2. как велик перечень ключей (source,target), по условиям


Код: sql
1.
2.
AND NOT EXISTS ( SELECT 1 FROM road_delnodes AS rdn WHERE rdn.gid = graph.source) 
AND NOT EXISTS ( SELECT 1 FROM road_delnodes AS rdn WHERE rdn.gid = graph.target)


--исчислим ли этот набор (или его срезы) снаружи (т.е. охвачено ли всё fk-ями) ?
-- если исчислим, и ожидаемо мал -- нельзя ли инвертировать NOT IN () в "=ANY(ARRAY(SELECT f_keys FROM blahblah EXCEPT ... FROM road_delnodes.))" ?
-- если можно -- то нет ли возможности составной btree_gist индекс поюзать ?
...
Рейтинг: 0 / 0
оптимизация запроса
    #38933242
pcadviser
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
qwwqpcadviserпропущено...


индексы есть и по the_geom, id, gid, source, target

с применением NOT EXISTS, тоже пробывал
результат - хуже

результат - в теме, чуть выше
гне надо пробЫвать, пробудете так всё на свете

надо сделать что просят, если лень читать
-- я вытащил наружу передаваемую в C динамику -- и прошу план по ней, а не по внешнему запросу

не понял Вашу мысль сразу, вот

Код: sql
1.
2.
3.
4.
5.
6.
7.
explain (ANALYZE, costs, buffers) 
SELECT * FROM (SELECT * FROM road_addedges UNION ALL 
SELECT * FROM road.edges) AS graph 
WHERE NOT EXISTS (SELECT 1 FROM road_deledges AS rd WHERE rd.gid = graph.id) 
AND NOT EXISTS ( SELECT 1 FROM road_delnodes AS rdn WHERE rdn.gid = graph.source) 
AND NOT EXISTS ( SELECT 1 FROM road_delnodes AS rdn WHERE rdn.gid = graph.target) 
AND NOT st_intersects(the_geom, geomfromewkt('SRID=4326;POLYGON((53 52,51 56,55 56,53 52))')) 



Nested Loop Anti Join (cost=64.00..3495310.19 rows=1 width=494) (actual time=0.016..13064.774 rows=8746687 loops=1)
Join Filter: (rdn.gid = road_addedges.target)
Buffers: shared hit=23563 read=728172, local hit=2
-> Nested Loop Anti Join (cost=64.00..3495271.57 rows=1 width=494) (actual time=0.015..9713.446 rows=8746687 loops=1)
Join Filter: (rdn.gid = road_addedges.source)
Buffers: shared hit=23563 read=728172, local hit=2
-> Hash Anti Join (cost=64.00..3495232.96 rows=1 width=494) (actual time=0.014..6385.614 rows=8746687 loops=1)
Hash Cond: (road_addedges.id = rd.gid)
Buffers: shared hit=23563 read=728172, local hit=2
-> Append (cost=0.00..3066717.59 rows=8788746 width=494) (actual time=0.006..4877.485 rows=8746689 loops=1)
Buffers: shared hit=23563 read=728172, local hit=1
-> Seq Scan on road_addedges (cost=0.00..125.50 rows=440 width=152) (actual time=0.005..0.007 rows=6 loops=1)
Filter: ((NOT (the_geom && '0103000020E610000001000000040000000000000000804A400000000000004A4000000000008049400000000000004C400000000000804B400000000000004C400000000000804A400000000000004A40'::geometry))
OR (NOT _st_intersects(the_geom, '0103000020E610000001000000040000000000000000804A400000000000004A4000000000008049400000000000004C400000000000804B400000000000004C400000000000804A400000000000004A40'::geometry)))
Buffers: local hit=1
-> Seq Scan on edges (cost=0.00..3066592.09 rows=8788306 width=494) (actual time=0.004..4187.377 rows=8746683 loops=1)
Filter: ((NOT (the_geom && '0103000020E610000001000000040000000000000000804A400000000000004A4000000000008049400000000000004C400000000000804B400000000000004C400000000000804A400000000000004A40'::geometry))
OR (NOT _st_intersects(the_geom, '0103000020E610000001000000040000000000000000804A400000000000004A4000000000008049400000000000004C400000000000804B400000000000004C400000000000804A400000000000004A40'::geometry)))
Buffers: shared hit=23563 read=728172
-> Hash (cost=34.00..34.00 rows=2400 width=4) (actual time=0.003..0.003 rows=2 loops=1)
Buckets: 1024 Batches: 1 Memory Usage: 1kB
Buffers: local hit=1
-> Seq Scan on road_deledges rd (cost=0.00..34.00 rows=2400 width=4) (actual time=0.001..0.001 rows=2 loops=1)
Buffers: local hit=1
-> Seq Scan on road_delnodes rdn (cost=0.00..34.00 rows=2400 width=4) (actual time=0.000..0.000 rows=0 loops=8746687)
-> Seq Scan on road_delnodes rdn (cost=0.00..34.00 rows=2400 width=4) (actual time=0.000..0.000 rows=0 loops=8746687)

Total runtime: 13494.066 ms
...
Рейтинг: 0 / 0
оптимизация запроса
    #38933251
pcadviser
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
qwwqpcadviserпропущено...


индексы есть и по the_geom, id, gid, source, target

с применением NOT EXISTS, тоже пробывал
результат - хуже

результат - в теме, чуть выше
гне надо пробЫвать, пробудете так всё на свете

надо сделать что просят, если лень читать
-- я вытащил наружу передаваемую в C динамику -- и прошу план по ней, а не по внешнему запросу

исходный вариант

Код: sql
1.
2.
3.
4.
5.
6.
explain (ANALYZE, costs, buffers) SELECT * FROM (SELECT * FROM road_addedges UNION ALL 
SELECT * FROM road.edges) AS graph 
WHERE id NOT IN (SELECT gid FROM road_deledges) 
AND source NOT IN (SELECT gid FROM road_delnodes) 
AND target NOT IN (SELECT gid FROM road_delnodes) 
AND NOT st_intersects(the_geom, geomfromewkt('SRID=4326;POLYGON((53 52,51 56,55 56,53 52))')) 



Result (cost=120.00..3133126.09 rows=1098593 width=494) (actual time=0.032..6952.084 rows=8746687 loops=1)
Buffers: shared hit=23595 read=728140, local hit=3
Append (cost=120.00..3133126.09 rows=1098593 width=494) (actual time=0.032..5770.488 rows=8746687 loops=1)
Buffers: shared hit=23595 read=728140, local hit=3
-> Seq Scan on road_addedges (cost=120.00..248.80 rows=55 width=152) (actual time=0.032..0.037 rows=6 loops=1)
Filter: ((NOT (hashed SubPlan 1)) AND (NOT (hashed SubPlan 2)) AND (NOT (hashed SubPlan 3)) AND ((NOT (the_geom && '0103000020E610000001000000040000000000000000804A400000000000004A4000000000008049400000000000004C400000000000804B400000000000004C400000000000804A400000000000004A40'::geometry))
OR (NOT _st_intersects(the_geom, '0103000020E610000001000000040000000000000000804A400000000000004A4000000000008049400000000000004C400000000000804B400000000000004C400000000000804A400000000000004A40'::geometry))))
Buffers: local hit=2
SubPlan 1
-> Seq Scan on road_deledges (cost=0.00..34.00 rows=2400 width=4) (actual time=0.001..0.001 rows=2 loops=2)
Buffers: local hit=2
SubPlan 2
-> Seq Scan on road_delnodes (cost=0.00..34.00 rows=2400 width=4) (actual time=0.001..0.001 rows=0 loops=2)
SubPlan 3
-> Seq Scan on road_delnodes (cost=0.00..34.00 rows=2400 width=4) (actual time=0.001..0.001 rows=0 loops=2)
-> Seq Scan on edges (cost=120.00..3132877.29 rows=1098538 width=494) (actual time=0.030..5074.961 rows=8746681 loops=1)
Filter: ((NOT (hashed SubPlan 1)) AND (NOT (hashed SubPlan 2)) AND (NOT (hashed SubPlan 3)) AND ((NOT (the_geom && '0103000020E610000001000000040000000000000000804A400000000000004A4000000000008049400000000000004C400000000000804B400000000000004C400000000000804A400000000000004A40'::geometry))
OR (NOT _st_intersects(the_geom, '0103000020E610000001000000040000000000000000804A400000000000004A4000000000008049400000000000004C400000000000804B400000000000004C400000000000804A400000000000004A40'::geometry))))
Buffers: shared hit=23595 read=728140, local hit=1
SubPlan 1
-> Seq Scan on road_deledges (cost=0.00..34.00 rows=2400 width=4) (actual time=0.001..0.001 rows=2 loops=2)
Buffers: local hit=2
SubPlan 2
-> Seq Scan on road_delnodes (cost=0.00..34.00 rows=2400 width=4) (actual time=0.001..0.001 rows=0 loops=2)
SubPlan 3
-> Seq Scan on road_delnodes (cost=0.00..34.00 rows=2400 width=4) (actual time=0.001..0.001 rows=0 loops=2)

Total runtime: 7291.332 ms
...
Рейтинг: 0 / 0
оптимизация запроса
    #38933257
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
pcadviser,

1)очень полезно сделать analyze для road_deledges и для road_delnodes

2)а какую собственно производительность вы ожидаете от запроса который возвращает 9M строк и дальше еще что то с ними в сишном коде делает? Тем более что судя по цифрам именно сишная хранимка (и даже не запрос в ней) все время и тратят.

--Maxim Boguk
www.postgresql-consulting.ru
...
Рейтинг: 0 / 0
оптимизация запроса
    #38933259
pcadviser
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
qwwq2. как велик перечень ключей (source,target), по условиям


Код: sql
1.
2.
AND NOT EXISTS ( SELECT 1 FROM road_delnodes AS rdn WHERE rdn.gid = graph.source) 
AND NOT EXISTS ( SELECT 1 FROM road_delnodes AS rdn WHERE rdn.gid = graph.target)



--исчислим ли этот набор (или его срезы) снаружи (т.е. охвачено ли всё fk-ями) ?
-- если исчислим, и ожидаемо мал -- нельзя ли инвертировать NOT IN () в "=ANY(ARRAY(SELECT f_keys FROM blahblah EXCEPT ... FROM road_delnodes.))" ?
-- если можно -- то нет ли возможности составной btree_gist индекс поюзать ?

набор исчислим - до 1000 записей, примерно

не смог разобрать -
инвертировать NOT IN () в "=ANY(ARRAY( SELECT f_keys FROM blahblah EXCEPT ... FROM road_delnodes .))" ?
...
Рейтинг: 0 / 0
оптимизация запроса
    #38933261
pcadviser
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Maxim Bogukдля road_deledges и для road_delnodes

1)
road_deledges и road_delnodes - временные таблицы
что за analyze к ним сделать?

2)
по производительности - хотелось бы по максимуму.

Спасибо за помощь!!!
...
Рейтинг: 0 / 0
оптимизация запроса
    #38933346
qwwq
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
pcadviser,

Код: sql
1.
SELECT COUNT(1) FROM edges 



PS скорее всего от скана вы не избавитесь. Т.ч. все про "не разобрал" -- не важно.
А обегание возврата внутри С не в ваших руках
...
Рейтинг: 0 / 0
оптимизация запроса
    #39125466
Pan_Alaverdy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Добрый день! с упрощением такого запроса кто нибудь может помочь?

SELECT
case
when orders.operator_comment LIKE '%#dostavleno%' THEN 'ДОСТАВЛЕН ТО'
when warehouse1.name = warehouse.name THEN 'ЛЕЖИТ НА ТТ'
ELSE 'НЕ ДОСТАВЛЕН'
end,
case when orders.delivery_method=1 or orders.delivery_method=4 THEN ''
when orders.delivery_method=2 THEN warehouse.name
ELSE 'Кто тут у нас?' end,
case
when orders.operator_comment LIKE '%#grandgotov%' and orders.operator_comment LIKE '%#megagotov%' THEN 'ОБА_ГОТОВЫ_АА'
when orders.operator_comment LIKE '%#astmelomangotov%' and orders.operator_comment LIKE '%#astmarwingotov%' THEN 'ОБА_ГОТОВЫ_АС'
when orders.operator_comment LIKE '%#damn%' THEN 'НЕТ_ТОВАРА'
when orders.operator_comment LIKE '%#grandgotov%' THEN 'ГРАНД_СОБРАЛ'
when orders.operator_comment LIKE '%#megagotov%' THEN 'МЕГА_СОБРАЛ'
when orders.operator_comment LIKE '%#astmelomangotov%' THEN 'АСТ_МЕГА_СОБРАЛ'
when orders.operator_comment LIKE '%##astmarwingotov%' THEN 'АСТ_МАРВИН_СОБРАЛ'
ELSE 'НЕГОТОВ'
end,
extract(year from orders.order_date) as year,
extract(month from orders.order_date) as month,
extract(hour from orders.order_date) as hour,
extract(week from orders.order_date) as week,
date(orders.order_date),
orders.order_id,
orders.customer_surname,
orders.points_spent,
orders.bonus_points,
orders.customer_name,
orders.customer_secondname,
orders.customer_phone,
orders.customer_mobile,
orders.customer_email,
orders.delivery_region,
orders.delivery_city,
orders.delivery_microdistrict,
orders.delivery_street,
orders.delivery_house,
orders.delivery_apartment,
orders.delivery_zip_code,
orders.delivery_comment,
orders.retail_outlet_name,
orders.retail_outlet_address,
orders.retail_outlet_phone,
orders.retail_outlet_email,
orders.retail_outlet_warehouse_token,
(orders.delivery_cost+orders.order_cost) as itog,
orders.ic,
orders.delivery_method_description,
orders.delivery_date,
orders.delivery_time_of_day,
orders.delivery_cost,
orders.order_cost,
orders.order_date,
shipment.warehouse_token,
item.name_eshop,
item.id_ax,
item.name_ax,
item.category,
item.price,
item.quantity,
delivery_methods.caption,
order_conditions.caption,
order_states.caption,
orders.responsible,
warehouse1.name,
warehouse.name,
payment_methods.caption,
action_journal_goods_item_shipment_state.action_comment
FROM
imm.orders
INNER JOIN imm.item ON (orders.order_id = item.order_id)
INNER JOIN dictionaries.delivery_methods ON (orders.delivery_method = delivery_methods.id)
INNER JOIN dictionaries.order_conditions ON (orders.order_condition = order_conditions.id)
INNER JOIN dictionaries.order_states ON (orders.order_state = order_states.id)
INNER JOIN dictionaries.payment_methods ON(orders.payment_method = payment_methods.id),
imm.shipment
LEFT JOIN imm.action_journal_goods_item_shipment_state j ON j.id=(select max(id) from imm.action_journal_goods_item_shipment_state where reference_id = shipment.id),
imm.warehouse warehouse1,
imm.warehouse,
imm.action_journal_goods_item_shipment_state
WHERE
item.id = shipment.order_goods_item_id AND
warehouse1.token = shipment.warehouse_token AND
warehouse.token = orders.retail_outlet_warehouse_token and
orders.order_date > '2015-11-16' and orders.delivery_comment like '%expressdelivery%'
...
Рейтинг: 0 / 0
оптимизация запроса
    #39126546
Hawkmoon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Pan_Alaverdy,
0. шагом марш новую тему на форуме:
http://www.sql.ru/forum/actualpost.aspx?bid=7
создавать. Хватит наверх мусор 100летней давности поднимать.
Тебе ответят все те же люди.
1. explain (запрос)? Причем отформатированный с сохранением пробелов (юзай тег src)
2. таблицы и индексы по ним?
...
Рейтинг: 0 / 0
57 сообщений из 57, показаны все 3 страниц
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / оптимизация запроса
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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