powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Задача на оптимизацию. Поразмять мозги.
26 сообщений из 26, показаны все 2 страниц
Задача на оптимизацию. Поразмять мозги.
    #39124627
FrankDobski
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Запрос находит суммарную выручку от продажи билетов по каждой из планет.

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
-- здесь можно создавать индексы, если угодно
-- CREATE INDEX idx1 ON Commander(name);

-- Вспомогательная функция, считающая количество пассажиров, летевших 
-- на планету _planet_id в звездолете класса _class
CREATE OR REPLACE FUNCTION GetPaxCount(_planet_id INT, _class INT) RETURNS BIGINT AS $$
SELECT COUNT(Pax.id)
FROM Planet P JOIN Flight F ON P.id=F.planet_id
JOIN Booking B ON B.flight_id = F.id
JOIN Spacecraft S ON F.spacecraft_id = S.id
JOIN Pax ON B.pax_id = Pax.id
WHERE S.class = _class AND P.id = _planet_id;
$$ LANGUAGE SQL IMMUTABLE;

-- Запрос, нуждающийся в ускорении. 
-- Сигнатуру функции менять нельзя
CREATE OR REPLACE FUNCTION Benchmark2()
RETURNS TABLE(planet_id INT, spacecraft_class INT, takings BIGINT) AS $$

-- Тело функции менять можно
SELECT Price.planet_id, Price.spacecraft_class, Price.price * GetPaxCount(Price.planet_id, Price.spacecraft_class) FROM Price;
$$ LANGUAGE SQL IMMUTABLE;



После выполнения некоторых действий время выполнения отдельно взятого запроса уменьшится примерно в 10-30 раз.


Скрипт инициализации.

Код: 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.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
CREATE OR REPLACE FUNCTION GenerateData() RETURNS VOID AS $$
BEGIN
-- ================================
-- Перечисление государственных устройств
INSERT INTO Government(value)
SELECT unnest(ARRAY['Анархия', 'Коммунизм', 'Конфедерация', 'Олигархия', 'Демократия', 'Диктатура', 'Феодализм']);

-- ================================
-- Капитаны со случайными рейтингами
WITH Names AS (
  SELECT unnest(ARRAY['Громозека', 'Ким', 'Буран', 'Зелёный', 'Горбовский', 'Ийон Тихий', 'Форд Префект', 'Комов', 'Каммерер', 'Гагарин', 'Титов', 'Леонов', 'Крикалев', 'Армстронг', 'Олдрин']) AS name
), Ratings AS (
  select enumsortorder AS rating_num, enumlabel::Rating AS rating_value
  from pg_catalog.pg_enum
  WHERE enumtypid = 'rating'::regtype ORDER BY enumsortorder
),
NameRating AS (
  SELECT name, (0.5 + random() * (SELECT MAX(rating_num) FROM Ratings))::int
  AS rating_num FROM Names
)
INSERT INTO Commander(name, rating)
SELECT name, rating_value FROM NameRating JOIN Ratings USING(rating_num);

-- ================================
-- Перечисление планет со случайными расстояниями и правительствами
WITH PlanetNames AS (
  SELECT unnest(ARRAY[
    'Tibedied', 'Qube', 'Leleer', 'Biarge', 'Xequerin', 'Tiraor', 'Rabedira', 'Lave',
    'Zaatxe', 'Diusreza', 'Teaatis', 'Riinus', 'Esbiza', 'Ontimaxe', 'Cebetela', 'Ceedra',
    'Rizala', 'Atriso', 'Teanrebi', 'Azaqu', 'Retila', 'Sotiqu', 'Inleus', 'Onrira', 'Ceinzala',
    'Biisza', 'Legees', 'Quator', 'Arexe', 'Atrabiin', 'Usanat', 'Xeesle', 'Oreseren', 'Inera',
    'Inus', 'Isence', 'Reesdice', 'Terea', 'Orgetibe', 'Reorte', 'Ququor', 'Geinona',
    'Anarlaqu', 'Oresri', 'Esesla', 'Socelage', 'Riedquat', 'Gerege', 'Usle', 'Malama',
    'Aesbion', 'Alaza', 'Xeaqu', 'Raoror', 'Ororqu', 'Leesti', 'Geisgeza', 'Zainlabi',
    'Uscela', 'Isveve', 'Tioranin', 'Learorce', 'Esusti', 'Ususor', 'Maregeis', 'Aate',
    'Sori', 'Cemave', 'Arusqudi', 'Eredve', 'Regeatge', 'Edinso', 'Ra', 'Aronar',
    'Arraesso', 'Cevege', 'Orteve', 'Geerra', 'Soinuste', 'Erlage', 'Xeaan', 'Veis',
    'Ensoreus', 'Riveis', 'Bivea', 'Ermaso', 'Velete', 'Engema', 'Atrienxe', 'Beusrior',
    'Ontiat', 'Atarza', 'Arazaes', 'Xeeranre', 'Quzadi', 'Isti', 'Digebiti', 'Leoned',
    'Enzaer', 'Teraed'
  ]) AS name
)
INSERT INTO Planet(name, distance, government_id)
SELECT name, (random() * 1000)::numeric(5,2), (0.5 + random() * (SELECT COUNT(*) FROM Government))::int
FROM PlanetNames;

-- ================================
-- Стоимость билета увеличивается с увеличением расстояния и повышением класса корабля
WITH Planets AS (
  SELECT id, distance FROM Planet
), Classes AS (
  SELECT generate_series(1,3) AS spacecraft_class
)
INSERT INTO Price (planet_id, spacecraft_class, price)
SELECT id, spacecraft_class, (random() * 1000 + distance + 300*(4 - spacecraft_class))::INT
FROM Planets CROSS JOIN Classes;

-- ================================
-- Перечисление кораблей со случайными классами и вместимостью
WITH Names AS (
  SELECT unnest(ARRAY[
      'Кедр', 'Орел', 'Сокол', 'Беркут', 'Ястреб', 'Чайка', 'Рубин', 'Алмаз', 'Аргон', 'Амур', 'Байкал', 'Антей', 'Буран'
  ]) AS name
)
INSERT INTO Spacecraft(name, capacity, class)
SELECT name, (3+random()*20)::INT, (0.5+random()*3)::INT
FROM Names;

-- ================================
-- Случайные полеты
WITH MaxValues AS (
  SELECT (SELECT MAX(id) FROM Spacecraft) AS spacecraft,
  (SELECT MAX(id) FROM Commander) AS commander,
  (SELECT MAX(id) FROM Planet) AS planet
),
Flights AS (
  SELECT generate_series(1, 50000) AS id
)
INSERT INTO Flight(id, spacecraft_id, commander_id, planet_id, date)
SELECT id, (0.5 + random()*spacecraft)::INT,
    (0.5 + random()*commander)::INT,
    (0.5 + random()*planet)::INT,
    ('2084-01-01'::DATE + random()*365*5 * INTERVAL '1 day')::DATE
FROM MaxValues CROSS JOIN Flights;

-- ================================
-- Случайные пассажиры
WITH Paxes AS(
  SELECT generate_series(1, 10000) AS id
), Races AS (
  select enumsortorder AS race_num, enumlabel::Race AS race_value
  from pg_catalog.pg_enum
  WHERE enumtypid = 'race'::regtype ORDER BY enumsortorder
), PaxRace AS (
  SELECT id, 'Pax' || id::TEXT AS name, (0.5 + random() * (SELECT MAX(race_num) FROM Races))::int
  AS race_num FROM Paxes
)
INSERT INTO Pax(id, name, race)
SELECT id, name, race_value FROM PaxRace JOIN Races USING(race_num);

-- ================================
-- Случайные бронирования
WITH Bookings AS (
  SELECT generate_series(1, 200000) AS id
),
MaxValues AS (
  SELECT (SELECT MAX(id) FROM Pax) AS pax,
  (SELECT MAX(id) FROM Flight) AS flight
)
INSERT INTO Booking(ref_num, pax_id, flight_id)
SELECT substring(md5(id::TEXT)::TEXT for 10), (0.5 + random() * pax)::INT, (0.5 + random() * flight)::INT
FROM Bookings CROSS JOIN MaxValues;

END;
$$ LANGUAGE plpgsql;

SELECT GenerateData();




Схема БД

Код: 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.
DROP TABLE IF EXISTS Booking;
DROP TABLE IF EXISTS Pax;
DROP TYPE IF EXISTS Race;
DROP TABLE IF EXISTS Price;
DROP TABLE IF EXISTS Flight;
DROP TABLE IF EXISTS Spacecraft;
DROP TABLE IF EXISTS Commander;
DROP TYPE IF EXISTS Rating;
DROP TABLE IF EXISTS Planet;
DROP TABLE IF EXISTS Government;

-- Справочник политических строев
CREATE TABLE Government(id SERIAL PRIMARY KEY, value TEXT UNIQUE);

-- Планета, её название, расстояние до Земли, политический строй
CREATE TABLE Planet(
  id SERIAL PRIMARY KEY,
  name TEXT UNIQUE,
  distance NUMERIC(5,2),
  government_id INT REFERENCES Government);

-- Значения рейтинга пилотов
CREATE TYPE Rating AS ENUM('Harmless', 'Poor', 'Average', 'Competent', 'Dangerous', 'Deadly', 'Elite');

-- Пилот корабля
CREATE TABLE Commander(
  id SERIAL PRIMARY KEY,
  name TEXT,
  rating Rating);

-- Космический корабль, вместимость пассажиров и класс корабля
CREATE TABLE Spacecraft(
  id SERIAL PRIMARY KEY,
  capacity INT CHECK(capacity > 0),
  name TEXT UNIQUE,
  class INT CHECK(class BETWEEN 1 AND 3));

-- Полет на планету в означеную дату, выполняемый кораблем, пилотируемый капитаном
CREATE TABLE Flight(id INT PRIMARY KEY,
  spacecraft_id INT REFERENCES Spacecraft,
  commander_id INT REFERENCES Commander,
  planet_id INT REFERENCES Planet,
  date DATE
);

-- Стоимость полета до планеты на корабле означенного класса
CREATE TABLE Price(
  planet_id INT REFERENCES Planet,
  spacecraft_class INT CHECK(spacecraft_class BETWEEN 1 AND 3),
  price INT CHECK(price>0),
  UNIQUE(planet_id, spacecraft_class));

-- Раса пассажира
CREATE TYPE Race AS ENUM('Elves', 'Men', 'Trolls');

-- Пассажир
CREATE TABLE Pax(
  id INT PRIMARY KEY,
  name TEXT,
  race Race);

-- Резервирование места на полет
CREATE TABLE Booking(
  ref_num TEXT PRIMARY KEY,
  pax_id INT REFERENCES Pax,
  flight_id INT REFERENCES Flight);


Были использованы разные индексы, но что то всё бестолку. Помогитие решить.
...
Рейтинг: 0 / 0
Задача на оптимизацию. Поразмять мозги.
    #39124634
Фотография vyegorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
FrankDobskiПосле выполнения некоторых действий время выполнения отдельно взятого запроса уменьшится примерно в 10-30 раз.

А что за действия? И можно глянуть `EXPLAIN (analyze, buffers)` для разных по скорости вариантов?
...
Рейтинг: 0 / 0
Задача на оптимизацию. Поразмять мозги.
    #39124807
Ivan Durak
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Модель непонятна. Здесь 2 Таблицы фактов - полеты и букинги!!
Достаточно 1-й такого вида:

например Booking будет иметь такую структуру:
ref_num, pax_id, spacecraft_id, commander_id, planet_id, date.

После чего тривиальным запросом получаются все суммы.
Код: sql
1.
2.
3.
4.
5.
SELECT P.planet_id, P.spacecraft_class, P.price * count(B.pax_id)
FROM Booking B
inner join Spacecraft S ON B.spacecraft_id = S.id
inner join Price P on P.planet_id = B.planet_id and P.spacecraft_class = S.class
group by P.planet_id, P.spacecraft_class, P.price;



Мало того, тут можно еще денормализовать засунув в этот факт кроме spacecraft_id еще и spacecraft_class -
минус один джоин на Spacecraft.

Мало того можно и дальше денормализовать избавившись от таблицы price
Цену запихнуть сразу в Booking.
...
Рейтинг: 0 / 0
Задача на оптимизацию. Поразмять мозги.
    #39124815
Ivan Durak
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
а сейчас кстати весь ужас в кореллированной функции GetPaxCount
которая вызывается столько раз - сколько записей в price.
Переписать это - уже на порядок все шустрее будет
...
Рейтинг: 0 / 0
Задача на оптимизацию. Поразмять мозги.
    #39124819
Ivan Durak
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: sql
1.
2.
3.
4.
5.
6.
SELECT P.planet_id, P.spacecraft_class, P.price * count(B.pax_id)
FROM Booking B
inner join Flight F on B.flight_id = F.id
inner join Spacecraft S ON F.spacecraft_id = S.id
inner join Price P on P.planet_id = F.planet_id and P.spacecraft_class = S.class
group by P.planet_id, P.spacecraft_class, P.price;


например так.

А индексами уже тюнинговать в самам конце. Когда с моделью все ок
...
Рейтинг: 0 / 0
Задача на оптимизацию. Поразмять мозги.
    #39124945
FrankDobski
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Ivan Durak, вся проблема в том, что менять нельзя структуру базы данных и необходимо оптимизировать именно данный запрос с помощью индексов или изменив процедуру.
...
Рейтинг: 0 / 0
Задача на оптимизацию. Поразмять мозги.
    #39125010
qwwq
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
FrankDobskiIvan Durak, вся проблема в том, что менять нельзя структуру базы данных и необходимо оптимизировать именно данный запрос с помощью индексов или изменив процедуру.
если целостность поддерживается -- то у вас минимум один лишний джойн. (ни на что особо не влияет)

использование immutable для таблично обусловленых данных -- опасный хак. требует безусловной перезагрузки ф-ии послс изменения данных. (считай -- в тексте триггеров на каждой таблице обязаны висеть тексты create or replace-ов этих ф--й, что приведет к очередям на тела ф--й.). т.е. это скорее баг, за который надо убивать. (в 1-м месте для константы БД этим пользуюсь сам).

ну и если не опускаться до бессмысленных требований -- то как--то так:

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
EXPLAIN (ANALYZE , VERBOSE off, COSTS on, BUFFERS on, TIMING off )
WITH cnts as (
	SELECT COUNT( B.pax_id /*Pax.id*/) cnt

		,S.class AS spacecraft_class
		,P.id AS planet_id
	FROM Planet P
	JOIN Flight F ON P.id=F.planet_id
	JOIN Booking B ON B.flight_id = F.id
	JOIN Spacecraft S ON F.spacecraft_id = S.id
	--*/JOIN Pax ON B.pax_id = Pax.id
	GROUP BY 
		S.class
		,P.id
	)
SELECT Price.planet_id, Price.spacecraft_class, Price.price * cnt
FROM Price
LEFT JOIN cnts USING(planet_id, spacecraft_class);


------------------------------------
Hash Right Join (cost=11610.04..11620.56 rows=300 width=20) (actual rows=300 loops=1)
Hash Cond: ((cnts.planet_id = price.planet_id) AND (cnts.spacecraft_class = price.spacecraft_class))
Buffers: shared hit=1597
CTE cnts
-> HashAggregate (cost=11597.54..11600.54 rows=300 width=12) (actual rows=300 loops=1)
Group Key: s.class, p.id
Buffers: shared hit=1595
-> Hash Join (cost=2823.54..10097.54 rows=200000 width=12) (actual rows=200000 loops=1)
Hash Cond: (b.flight_id = f.id)
Buffers: shared hit=1595
-> Seq Scan on booking b (cost=0.00..3274.00 rows=200000 width=8) (actual rows=200000 loops=1)
Buffers: shared hit=1274
-> Hash (cost=2198.54..2198.54 rows=50000 width=12) (actual rows=50000 loops=1)
Buckets: 8192 Batches: 1 Memory Usage: 1758kB
Buffers: shared hit=321
-> Hash Join (cost=4.54..2198.54 rows=50000 width=12) (actual rows=50000 loops=1)
Hash Cond: (f.spacecraft_id = s.id)
Buffers: shared hit=321
-> Hash Join (cost=3.25..1509.75 rows=50000 width=12) (actual rows=50000 loops=1)
Hash Cond: (f.planet_id = p.id)
Buffers: shared hit=320
-> Seq Scan on flight f (cost=0.00..819.00 rows=50000 width=12) (actual rows=50000 loops=1)
Buffers: shared hit=319
-> Hash (cost=2.00..2.00 rows=100 width=4) (actual rows=100 loops=1)
Buckets: 1024 Batches: 1 Memory Usage: 3kB
Buffers: shared hit=1
-> Seq Scan on planet p (cost=0.00..2.00 rows=100 width=4) (actual rows=100 loops=1)
Buffers: shared hit=1
-> Hash (cost=1.13..1.13 rows=13 width=8) (actual rows=13 loops=1)
Buckets: 1024 Batches: 1 Memory Usage: 1kB
Buffers: shared hit=1
-> Seq Scan on spacecraft s (cost=0.00..1.13 rows=13 width=8) (actual rows=13 loops=1)
Buffers: shared hit=1
-> CTE Scan on cnts (cost=0.00..6.00 rows=300 width=16) (actual rows=300 loops=1)
Buffers: shared hit=1595
-> Hash (cost=5.00..5.00 rows=300 width=12) (actual rows=300 loops=1)
Buckets: 1024 Batches: 1 Memory Usage: 11kB
Buffers: shared hit=2
-> Seq Scan on price (cost=0.00..5.00 rows=300 width=12) (actual rows=300 loops=1)
Buffers: shared hit=2
Planning time: 0.665 ms
Execution time: 298.093 ms


все индексы для вторички созданы, но не используются для массового расчета

гораздо веселее , что timing ON подвешивает план на порядок.
...
Рейтинг: 0 / 0
Задача на оптимизацию. Поразмять мозги.
    #39125011
Ivan Durak
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
FrankDobskiIvan Durak, вся проблема в том, что менять нельзя структуру базы данных и необходимо оптимизировать именно данный запрос с помощью индексов или изменив процедуру.
последний вариант пробовал?

CREATE OR REPLACE FUNCTION Benchmark2()
RETURNS TABLE(planet_id INT, spacecraft_class INT, takings BIGINT) AS $$

SELECT P.planet_id, P.spacecraft_class, P.price * count(B.pax_id)
FROM Booking B
inner join Flight F on B.flight_id = F.id
inner join Spacecraft S ON F.spacecraft_id = S.id
inner join Price P on P.planet_id = F.planet_id and P.spacecraft_class = S.class
group by P.planet_id, P.spacecraft_class, P.price;

$$ LANGUAGE SQL IMMUTABLE;
----------------------------
p.s. А структуру оптимизировать все равно стоит
...
Рейтинг: 0 / 0
Задача на оптимизацию. Поразмять мозги.
    #39125014
qwwq
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
qwwq
использование immutable для таблично обусловленых данных
читать -- "функций" (эхолалия детектед)
...
Рейтинг: 0 / 0
Задача на оптимизацию. Поразмять мозги.
    #39125019
qwwq
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
поправил
Код: sql
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.
EXPLAIN (ANALYZE , VERBOSE off, COSTS on, BUFFERS on, TIMING off )
WITH cnts as (
	SELECT COUNT( B.pax_id /*Pax.id*/) cnt

		,S.class AS spacecraft_class
		,P.id AS planet_id
	FROM Planet P
	JOIN Flight F ON P.id=F.planet_id
	JOIN Booking B ON B.flight_id = F.id
	JOIN Spacecraft S ON F.spacecraft_id = S.id
	--*/JOIN Pax ON B.pax_id = Pax.id
	GROUP BY 
		S.class
		,P.id
	)
SELECT Price.planet_id, Price.spacecraft_class, Price.price * cnt
FROM Price
LEFT JOIN cnts USING(planet_id, spacecraft_class);


------------------------------------
Hash Right Join  (cost=11610.04..11620.56 rows=300 width=20) (actual rows=300 loops=1)
  Hash Cond: ((cnts.planet_id = price.planet_id) AND (cnts.spacecraft_class = price.spacecraft_class))
  Buffers: shared hit=1597
  CTE cnts
    ->  HashAggregate  (cost=11597.54..11600.54 rows=300 width=12) (actual rows=300 loops=1)
          Group Key: s.class, p.id
          Buffers: shared hit=1595
          ->  Hash Join  (cost=2823.54..10097.54 rows=200000 width=12) (actual rows=200000 loops=1)
                Hash Cond: (b.flight_id = f.id)
                Buffers: shared hit=1595
                ->  Seq Scan on booking b  (cost=0.00..3274.00 rows=200000 width=8) (actual rows=200000 loops=1)
                      Buffers: shared hit=1274
                ->  Hash  (cost=2198.54..2198.54 rows=50000 width=12) (actual rows=50000 loops=1)
                      Buckets: 8192  Batches: 1  Memory Usage: 1758kB
                      Buffers: shared hit=321
                      ->  Hash Join  (cost=4.54..2198.54 rows=50000 width=12) (actual rows=50000 loops=1)
                            Hash Cond: (f.spacecraft_id = s.id)
                            Buffers: shared hit=321
                            ->  Hash Join  (cost=3.25..1509.75 rows=50000 width=12) (actual rows=50000 loops=1)
                                  Hash Cond: (f.planet_id = p.id)
                                  Buffers: shared hit=320
                                  ->  Seq Scan on flight f  (cost=0.00..819.00 rows=50000 width=12) (actual rows=50000 loops=1)
                                        Buffers: shared hit=319
                                  ->  Hash  (cost=2.00..2.00 rows=100 width=4) (actual rows=100 loops=1)
                                        Buckets: 1024  Batches: 1  Memory Usage: 3kB
                                        Buffers: shared hit=1
                                        ->  Seq Scan on planet p  (cost=0.00..2.00 rows=100 width=4) (actual rows=100 loops=1)
                                              Buffers: shared hit=1
                            ->  Hash  (cost=1.13..1.13 rows=13 width=8) (actual rows=13 loops=1)
                                  Buckets: 1024  Batches: 1  Memory Usage: 1kB
                                  Buffers: shared hit=1
                                  ->  Seq Scan on spacecraft s  (cost=0.00..1.13 rows=13 width=8) (actual rows=13 loops=1)
                                        Buffers: shared hit=1
  ->  CTE Scan on cnts  (cost=0.00..6.00 rows=300 width=16) (actual rows=300 loops=1)
        Buffers: shared hit=1595
  ->  Hash  (cost=5.00..5.00 rows=300 width=12) (actual rows=300 loops=1)
        Buckets: 1024  Batches: 1  Memory Usage: 11kB
        Buffers: shared hit=2
        ->  Seq Scan on price  (cost=0.00..5.00 rows=300 width=12) (actual rows=300 loops=1)
              Buffers: shared hit=2
Planning time: 0.665 ms
Execution time: 298.093 ms


...
Рейтинг: 0 / 0
Задача на оптимизацию. Поразмять мозги.
    #39125042
FrankDobski
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Ivan Durak, спасибо огромное. Голова забилась индексами из лекций и соответственно не на что другое внимание обращать не хотела. Спасибо.
...
Рейтинг: 0 / 0
Задача на оптимизацию. Поразмять мозги.
    #39127226
FrankDobski
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Ivan Durak,

а как лучше оптимизировать
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
CREATE OR REPLACE FUNCTION Benchmark3(_commander_name TEXT, _pax_count INT)
RETURNS TABLE(flight_id INT, commander_name TEXT, pax_count INT) AS $$

SELECT id, name, pax_count FROM (
    SELECT F.id, C.name
    FROM Commander C
    JOIN Flight F ON F.commander_id=C.id
    WHERE F.date BETWEEN '2084-04-01' AND '2084-04-15'
    AND C.name = _commander_name
) R
JOIN (
    SELECT F.id, COUNT(P.id)::INT AS pax_count
    FROM Flight F
    JOIN Booking B ON B.flight_id = F.id
    JOIN Pax P ON B.pax_id=P.id
    WHERE P.race='Men'
    GROUP BY F.id
) T USING(id) WHERE T.pax_count>_pax_count;
$$ LANGUAGE SQL IMMUTABLE;



мой вариант как то так
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
СREATE OR REPLACE FUNCTION Benchmark4(_commander_name TEXT, _pax_count INT)
RETURNS TABLE(flight_id INT, commander_name TEXT, pax_count INT) AS $$
SELECT F.id, COUNT(P.id)::INT AS pax_count
FROM Commander C
JOIN Flight F ON F.commander_id=C.id
JOIN Booking B ON B.flight_id = F.id
JOIN Pax P ON B.pax_id=P.id
WHERE P.race='Men' AND F.date BETWEEN '2084-04-01' AND '2084-04-15'
AND C.name = _commander_name GROUP BY F.id;
$$ LANGUAGE SQL IMMUTABLE;



это не окончательный вариант, но сейчас именно его пытаюсь крутить на машине и запустить, а из и него уже выбирать.
...
Рейтинг: 0 / 0
Задача на оптимизацию. Поразмять мозги.
    #39127375
qwwq
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
FrankDobski,

вам выше написали, что пользоваться IMMUTABLE в вашем случае нельзя.

ну и зачем сворачивать больше, если можно свернуть меньше ? вы так и не воткнулись.
...
Рейтинг: 0 / 0
Задача на оптимизацию. Поразмять мозги.
    #39127463
Ivan Durak
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Это вы там игру космическую делаете??
Так если еще не поздно - 100% незачем вам 2 факта - букинг и флайт! объединить в один - сразу все вычисления проще будут
...
Рейтинг: 0 / 0
Задача на оптимизацию. Поразмять мозги.
    #39127500
FrankDobski
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Ivan Durak,
ничего не строим задания это такие. stepic.org
...
Рейтинг: 0 / 0
Задача на оптимизацию. Поразмять мозги.
    #39127581
FrankDobski
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
qwwq,

Immutable использовать необходимо поскольку сигнатуру фунцкции менять нельзя.это задание
...
Рейтинг: 0 / 0
Задача на оптимизацию. Поразмять мозги.
    #39127640
qwwq
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
FrankDobski,

а теперь, мой маленький друг, пойдите и почитайте, что называется сигнатурой функции
http://www.postgresql.org/search/?u=/docs/9.4/&q=signature function

и каким боком тут
авторIMMUTABLE
STABLE
VOLATILE

These attributes inform the query optimizer about the behavior of the function. At most one choice can be specified. If none of these appear, VOLATILE is the default assumption.
оказались сигнатурой.


в вашем случае ф-я stable.
...
Рейтинг: 0 / 0
Задача на оптимизацию. Поразмять мозги.
    #39128149
FrankDobski
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
qwwq,
к сожалению stable, volatile не помогли.
...
Рейтинг: 0 / 0
Задача на оптимизацию. Поразмять мозги.
    #39128195
Lonepsycho
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
FrankDobskiqwwq,
к сожалению stable, volatile не помогли.

если вы про скорость, то да, это не поможет. да и qwwq вам говорил не про скорость, читайте заново и вчитывайтесь.
...
Рейтинг: 0 / 0
Задача на оптимизацию. Поразмять мозги.
    #39128230
FrankDobski
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Lonepsycho,

Код: plsql
1.
2.
3.
4.
5.
6.
SELECT * FROM Commander C
JOIN Flight F ON F.commander_id=C.id
JOIN (SELECT COUNT(B.pax_id) as count1 FROM BOOKING B WHERE COUNT (B.pax_id) > 2$
JOIN Pax P ON B.pax_id = P.id
WHERE F.date BETWEEN '2084-04-01' AND '2084-04-15' AND P.race='Men'
AND C.name = 'Ким';



Я только учусь работать с БД, а задания пройти хочется. Данный пример не работает. Помогите оптимизировать.
...
Рейтинг: 0 / 0
Задача на оптимизацию. Поразмять мозги.
    #39128234
Lonepsycho
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
FrankDobski,

я вижу синтаксическую ошибку. перепроверте.
...
Рейтинг: 0 / 0
Задача на оптимизацию. Поразмять мозги.
    #39128245
Lonepsycho
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
FrankDobski,

и да, говоря про оптимизацию. смотря на ваш запрос, вам нехочется добавить какой нибудь индекс?
...
Рейтинг: 0 / 0
Задача на оптимизацию. Поразмять мозги.
    #39128346
FrankDobski
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Lonepsycho,

я считаю что добавить надо индекс для flight.id. А вот с запросом не могли бы помочь?
...
Рейтинг: 0 / 0
Задача на оптимизацию. Поразмять мозги.
    #39128585
FrankDobski
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Ivan Durak,

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
    
    SELECT F.id, _commander_name, COUNT(P.id)::INT AS pax_count
    FROM Flight F
    JOIN Commander C ON F.commander_id=C.id
    JOIN Booking B ON B.flight_id = F.id
    JOIN Pax P ON B.pax_id=P.id
    WHERE P.race='Men' AND F.date BETWEEN '2084-04-01' AND '2084-04-15'
    AND C.name = _commander_name AND COUNT(P.id)>_pax_count
    GROUP BY (F.id);

это мой запрос. Ругается на выделенное. Подскажите как правильно сотавить запрос, чтобы не ругалось?
...
Рейтинг: 0 / 0
Задача на оптимизацию. Поразмять мозги.
    #39129373
Ivan Durak
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
мне уже лень...
...
Рейтинг: 0 / 0
Задача на оптимизацию. Поразмять мозги.
    #39129554
Фотография vyegorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
FrankDobski,

Выделенное перенести в `HAVING`.
...
Рейтинг: 0 / 0
26 сообщений из 26, показаны все 2 страниц
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Задача на оптимизацию. Поразмять мозги.
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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