-
Notifications
You must be signed in to change notification settings - Fork 69
Description
Описание проблемы
Есть 2 таблицы со следующей структурой:
CREATE TABLE public.valuation (
id bigserial NOT NULL,
cost numeric(20,6) NULL,
discount numeric(20,6) NULL,
cost_with_vat numeric(20,6) NULL,
vat_sum numeric(20,6) NULL,
vat_rate_code text NULL,
currency_code text NOT NULL,
CONSTRAINT valuation_pkey PRIMARY KEY (id)
);
CREATE TABLE public.orders (
id uuid NOT NULL DEFAULT gen_random_uuid(),
"number" text NOT NULL,
paid_online_on_delivery_id int8 NULL,
CONSTRAINT orders_pkey PRIMARY KEY (id)
);
CREATE UNIQUE INDEX udx_orders_number ON public.orders USING btree (number);
Связь
valuation.id --> orders.paid_online_on_delivery_id (1 к 1)
Количественные показатели таблиц
SELECT
COUNT(*),
MIN(id),
MAX(id)
FROM
valuation;
count | min | max |
---|---|---|
919648130 | 2 | 3581811089 |
SELECT
COUNT(*)
FROM
orders;
count |
---|
84808668 |
Таблица valuation разбита на партиции по диапазонам. Ключ партиционирования - id. Всего 100 партиций.
SELECT
*
from
pathman_partition_list
where
parent = 'valuation'::regclass
Результат запроса: https://gist.github.com/JanMihail/fd45cfef5ac24fe960e91a92c648b266#file-partitions-csv
Выполняю такой запрос
EXPLAIN (ANALYZE, BUFFERS)
SELECT
o.number,
v.id,
v.cost
FROM
orders o
JOIN valuation v ON v.id = o.paid_online_on_delivery_id
WHERE
o.number = '1104290452'
Результат
number | id | cost |
---|---|---|
1104290452 | 3512174003 | 0.000000 |
Nested Loop (cost=0.99..17.04 rows=1 width=14) (actual time=0.130..0.131 rows=1 loops=1)
Buffers: shared read=9 written=1
-> Index Scan using udx_orders_number on orders o (cost=0.57..8.59 rows=1 width=18) (actual time=0.059..0.060 rows=1 loops=1)
Index Cond: (number = '1104290452'::text)
Buffers: shared read=5
-> Custom Scan (RuntimeAppend) (cost=0.43..8.44 rows=1 width=23) (actual time=0.049..0.049 rows=1 loops=1)
Prune by: (o.paid_online_on_delivery_id = v.id)
Buffers: shared read=4 written=1
-> Index Scan using valuation_3513_pkey on valuation_3513 v_1 (cost=0.42..8.44 rows=1 width=13) (actual time=0.048..0.048 rows=1 loops=1)
Index Cond: (id = o.paid_online_on_delivery_id)
Buffers: shared read=4 written=1
Planning time: 12748.652 ms
Execution time: 0.198 ms
Из результатов вижу, что на планирование запроса ушло целых 12 секунд 748 миллисекунд.
Теперь я пробую сделать то же самое, но указываю в запросе конкретную партицию valuation_3513 из предыдущего EXPLAIN и смотрю на результаты.
EXPLAIN (ANALYZE, BUFFERS)
SELECT
o.number,
v.cost
FROM
orders o
JOIN partitions.valuation_3513 v ON v.id = o.paid_online_on_delivery_id
WHERE
o.number = '1104290452'
Результат
number | id | cost |
---|---|---|
1104290452 | 3512174003 | 0.000000 |
Nested Loop (cost=0.99..17.03 rows=1 width=15) (actual time=0.034..0.035 rows=1 loops=1)
Buffers: shared hit=9
-> Index Scan using udx_orders_number on orders o (cost=0.57..8.59 rows=1 width=18) (actual time=0.022..0.023 rows=1 loops=1)
Index Cond: (number = '1104290452'::text)
Buffers: shared hit=5
-> Index Scan using valuation_3513_pkey on valuation_3513 v (cost=0.42..8.44 rows=1 width=13) (actual time=0.010..0.010 rows=1 loops=1)
Index Cond: (id = o.paid_online_on_delivery_id)
Buffers: shared hit=4
Planning time: 0.351 ms
Execution time: 0.083 ms
Время планирования резко уменьшилось до 0.351 миллисекунд. Получается, что в первом запросе 12 секунд потратилось на поиск нужной партиции. Тогда я делаю следующий запрос.
EXPLAIN (ANALYZE, BUFFERS)
SELECT
id,
cost
FROM
valuation
where
id = 3512174003
Результат
id | cost |
---|---|
3512174003 | 0.000000 |
Append (cost=0.42..8.44 rows=1 width=12) (actual time=0.016..0.017 rows=1 loops=1)
Buffers: shared hit=4
-> Index Scan using valuation_3513_pkey on valuation_3513 (cost=0.42..8.44 rows=1 width=13) (actual time=0.016..0.016 rows=1 loops=1)
Index Cond: (id = '3512174003'::bigint)
Buffers: shared hit=4
Planning time: 0.128 ms
Execution time: 0.029 ms
При таком запросе на выбор нужной партиции затрачено всего 0.128 миллисекунд. Почему при JOIN по id (ключ партиционирования) время планирования резко подскакивает до 12 секунд? Что можно сделать, чтобы время планирования стало приемлемым?
Что я пытался делать:
- VACUUM ANALYZE всех партиций.
- REINDEX всех партиций.
- merge_range_partitions первых 80 партиций. По итогу оставалось 20 партиций. Результаты чуть лучше, но всё равно время планирования остаётся в пределах 4-7 секунд.
- Увеличение параметра shared_buffers и перезапуск сервера Postgres.
Ничего из этого не дало мне нужного результата.
Прошу помогите мне решить проблему.
Environment
SELECT * FROM pg_extension
extname | extowner | extnamespace | extrelocatable | extversion | extconfig | extcondition |
---|---|---|---|---|---|---|
plpgsql | 10 | 11 | false | 1.0 | ||
pg_repack | 10 | 2200 | false | 1.4.4 | ||
pg_trgm | 10 | 2200 | true | 1.3 | ||
pgcrypto | 10 | 2200 | true | 1.3 | ||
uuid-ossp | 10 | 2200 | true | 1.1 | ||
pg_pathman | 2672077 | 2200 | false | 1.5 | {47426753,47426764} | {,} |
SELECT version()
version |
---|
PostgreSQL 10.6 (Ubuntu 10.6-1.pgdg16.04+1) on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 5.4.0-6ubuntu1~16.04.10) 5.4.0 20160609, 64-bit |
SELECT pgpro_version()
SQL Error [42883]: ERROR: function pgpro_version() does not exist
SELECT pgpro_edition()
SQL Error [42883]: ERROR: function pgpro_edition() does not exist
SELECT get_pathman_lib_version()
SQL Error [42883]: ERROR: function get_pathman_lib_version() does not exist