172 похожих чатов

А можно как-то ускорить unnest? select unnest(p."attrs") from product_v2 p where

p."attrs" @> '{337}'

+------------------------------------------------------------------------------------------------------------------------------------------+
|QUERY PLAN |
+------------------------------------------------------------------------------------------------------------------------------------------+
|ProjectSet (cost=73.00..5004.83 rows=58060 width=4) (actual time=0.841..316.285 rows=155400 loops=1) |
| Output: unnest(attrs) |
| -> Bitmap Heap Scan on public.product_v2 p (cost=73.00..4670.98 rows=5806 width=92) (actual time=0.836..16.179 rows=5974 loops=1) |
| Output: attrs |
| Recheck Cond: (p.attrs @> '{337}'::integer[]) |
| Heap Blocks: exact=3245 |
| -> Bitmap Index Scan on product_v2_attrs_index (cost=0.00..71.55 rows=5806 width=0) (actual time=0.543..0.545 rows=5974 loops=1)|
| Index Cond: (p.attrs @> '{337}'::integer[]) |
|Planning Time: 0.070 ms |
|Execution Time: 598.275 ms |
+------------------------------------------------------------------------------------------------------------------------------------------+

19 ответов

20 просмотров

из 6т записей получаешь 155т. не думаю, что тут можно что-то радикально ускорить

Без переписывания кода постгреса -- это не слишком вероятно. (Лучшэ избавиться от необходимости unnest. Перенести его в код приложэния, если обработка на сервере не нужна -- либо нормализовать базу, если нужна).

Roman-Timofeev Автор вопроса

Нормализация делает больно + усложняет выборки

Roman Timofeev
Нормализация делает больно + усложняет выборки

Это заблуждение, делает больно в основном хранение данных в виде массивов

А какая версия PostgreSQL ( SELECT version(); ) и распределение количества элементов в массивах? Потому что (у меня v15.3) вот это: CREATE UNLOGGED TABLE product_v2 ( id bigint NOT NULL , attrs int[] NOT NULL ); INSERT INTO product_v2(id, attrs) SELECT 1 + n / 28 AS id, array_agg(n / 6000 + n % 800) FROM generate_series(1, 8000000) AS g(n) GROUP BY 1 ORDER BY id; CREATE INDEX ON product_v2 USING gin(attrs); VACUUM ANALYZE product_v2; Даёт вот такой план: ProjectSet (cost=55.46..6496.08 rows=50920 width=4) (actual time=4.158..16.461 rows=142576 loops=1) Output: unnest(attrs) -> Bitmap Heap Scan on public.product_v2 p (cost=55.46..6203.29 rows=5092 width=135) (actual time=4.146..8.404 rows=5092 loops=1) Output: id, attrs Recheck Cond: (p.attrs @> '{678}'::integer[]) Heap Blocks: exact=3096 -> Bitmap Index Scan on product_v2_attrs_idx (cost=0.00..54.19 rows=5092 width=0) (actual time=2.400..2.400 rows=5092 loops=1) Index Cond: (p.attrs @> '{678}'::integer[]) Planning Time: 0.397 ms Execution Time: 19.457 ms Обратите внимание, что почти все числа очень близки к Вашему (или даже немного хуже). А вот именно время unnest() почему-то сильно отличается (поэтому и вопросы выше).

Roman Timofeev
15.3

Странно. А по второму вопросу (может, там сильно разное количество элементов в разных записях, а не по ≈ 28, как в моём примере)? Ну и Вы можете просто попробовать показанный пример у себя — сравнимое получится время исполнения или совсем другое?

Roman-Timofeev Автор вопроса
Yaroslav Schekin
Странно. А по второму вопросу (может, там сильно р...

+--------------------------------------------------------------------------------------------------------------------------------------------+ |QUERY PLAN | +--------------------------------------------------------------------------------------------------------------------------------------------+ |Gather (cost=1000.00..9233.88 rows=5371 width=4) (actual time=0.177..472.081 rows=142576 loops=1) | | Output: (unnest(attrs)) | | Workers Planned: 2 | | Workers Launched: 2 | | -> ProjectSet (cost=0.00..7696.78 rows=22380 width=4) (actual time=0.020..194.753 rows=47525 loops=3) | | Output: unnest(attrs) | | Worker 0: actual time=0.020..282.544 rows=69328 loops=1 | | Worker 1: actual time=0.019..289.857 rows=70700 loops=1 | | -> Parallel Seq Scan on public.product_v2 p (cost=0.00..7568.10 rows=2238 width=136) (actual time=0.014..27.503 rows=1697 loops=3)| | Output: id, attrs | | Filter: (p.attrs @> '{678}'::integer[]) | | Rows Removed by Filter: 93541 | | Worker 0: actual time=0.013..39.872 rows=2476 loops=1 | | Worker 1: actual time=0.014..36.161 rows=2525 loops=1 | |Planning Time: 0.060 ms | |Execution Time: 919.878 ms | +--------------------------------------------------------------------------------------------------------------------------------------------+ кверя select unnest(p."attrs") from product_v2 p where p."attrs" @> '{678}'

Roman Timofeev
+-------------------------------------------------...

А Вы точно выполнили VACCUM ANALYZE (какие-то оценки совсем косые, и вид плана другой — видимо, из-за этого)? В любом случае, для тестирования можно SET enable_seqscan = off (ну и/или отключить параллелизм), чтобы план получился такой же. Тем не менее, уже кажется, что что-то сильно не так...

Roman-Timofeev Автор вопроса
Yaroslav Schekin
А Вы точно выполнили VACCUM ANALYZE (какие-то оцен...

Ок, позвал ещё раз VACUUM ANALYZE. Стало лучше +----------------------------------------------------------------------------------------------------------------------------------------+ |QUERY PLAN | +----------------------------------------------------------------------------------------------------------------------------------------+ |ProjectSet (cost=58.15..6607.32 rows=54380 width=4) (actual time=0.788..293.715 rows=142576 loops=1) | | Output: unnest(attrs) | | -> Bitmap Heap Scan on public.product_v2 p (cost=58.15..6294.63 rows=5438 width=136) (actual time=0.777..14.200 rows=5092 loops=1) | | Output: id, attrs | | Recheck Cond: (p.attrs @> '{678}'::integer[]) | | Heap Blocks: exact=3096 | | -> Bitmap Index Scan on product_v2_attrs_idx (cost=0.00..56.79 rows=5438 width=0) (actual time=0.492..0.494 rows=5092 loops=1)| | Index Cond: (p.attrs @> '{678}'::integer[]) | |Planning Time: 0.068 ms | |Execution Time: 554.375 ms | +----------------------------------------------------------------------------------------------------------------------------------------+

Roman Timofeev
Ок, позвал ещё раз VACUUM ANALYZE. Стало лучше +-...

Т.е. получается: ProjectSet (cost=58.15..6607.32 rows=54380 width=4) (actual time=0.788..293.715 rows=142576 loops=1) -- у Вас ProjectSet (cost=55.46..6496.08 rows=50920 width=4) (actual time=4.158..16.461 rows=142576 loops=1) -- у меня Хмм... да не может быть моё [очень] старое "железо" почти в 20 раз лучше Вашего. ;) Может, там какая-то throttled ("зажатая" по ресурсам или с кем-то их делящая так, что ей почти ничего не остаётся) VM, или что-то в этом роде? В общем, мне кажется, что стоит в эту сторону посмотреть для начала.

Yaroslav Schekin
А какая версия PostgreSQL ( SELECT version(); ) и ...

Мне любопытно -- что на том хосте говорит cat /proc/cpuinfo (Похожэ, L2 кэш мегабайт 8).

Roman-Timofeev Автор вопроса
Ilya Anfimov
Мне любопытно -- что на том хосте говорит cat /pro...

Это мой ноут, но там Ryzen 7 4800HS и SSD, а сам pg не в контейнере.

Roman Timofeev
Это мой ноут, но там Ryzen 7 4800HS и SSD, а сам p...

Мне любопытнее было -- что у Ярослава. Но про седьмой мобильный райзен тожэ понял, спасибо.

Roman Timofeev
Это мой ноут, но там Ryzen 7 4800HS и SSD, а сам p...

Кстатида, надо на ноуте тожэ попробовать. (Так-то почти везде у меня -- unnest в этом запросе в 5 раз медленнее, чем выборка. В 20 на ноуте -- понятно. А вот где всего вдвое? Точнее, дажэ примерно той жэ скорости?)

Roman Timofeev
Это мой ноут, но там Ryzen 7 4800HS и SSD, а сам p...

По крайней мере SSD тут ни при чём — тест-то именно в RAM. Казалось бы (но я уже давно не разбираюсь в процессорах!), Ваш должен быть +- то же самое на single thread (но поновее)... может, performance profile (или как там оно называется в Вашем дистрибутиве) не так настроен?

Roman Timofeev
Это мой ноут, но там Ryzen 7 4800HS и SSD, а сам p...

Хотя подождите, что это я (по поводу SSD)... а Вы EXPLAIN (ANALYZE, BUFFERS) показывали, или это я со своими планами перепутал? ;)

Похожие вопросы

Обсуждают сегодня

Всем привет, написал код ниже, но он выдает сегфолт, в чем причина? #include <stdio.h> #include <stdlib.h> #include <string.h> struct product { char *name; float price; };...
buzz базз
70
Здравствуйте. Задача состоит в том, чтобы сделать real-time чат в мобильном приложении. После передачи сообщения пользователем через веб-сокеты, для основного и долговременног...
🐾
5
Всем доброго дня, ребят подскажите пожалуйста, если в курсе по ассемблеру используется MASM32, могу ли я использовать FASM? В чем явная разница и будет ли у меня все работать?
Botsman
17
падает джоба хотя уже была собрана на соседнем namespace, куда капать? │ │ Copying blob sha256:2fa066caddb8f09a71082b03aa43046f79346a01d9c89e06a1f508bb1207dba5 427 │ │ Copyin...
Andrei St
5
Хотел бы спросить у знающих, правильную ли я выбрал книгу для начала изучения ассемблера Юрова В.И ? Или есть более лучшие книги для начала обучения?
Botsman
25
Книга Юрова В.И пойдёт для обучения?
Botsman
24
$params = [ 'formid' => 'feedbackForm', 'formTpl' => '@CODE: <form class="form-validate" data-id="ajax_form"> <fieldset class="margin-bottom-md"> ...
Pathologic
1
Люди добрые, помогите с идеями, потому что свои закончились. У клиента падает софтина в момент инициализации модуля OtlEventMonitor на RegisterWindowMessage('Gp/OtlTaskEvents/...
Михаил Усков
7
Тут просто дело в том, что я не могу сейчас дать такие подробности из за того что рассчитать это всё нереально. Этого проекта который я хочу сделать ещё даже не существует) И ...
🐾
8
> Примечательно, что новый владелец удаляет из GitHub любые жалобы, указывающие на подозрительную активность или смену владельца, и, видимо, рассчитывает на то, что пользовате...
Alex Sherbakov
2
Карта сайта