powered by simpleCommunicator - 2.0.54     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Можно ли оптимизировать данный запрос с json
17 сообщений из 17, страница 1 из 1
Можно ли оптимизировать данный запрос с json
    #39373138
Andrew B.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
На входе:
matrix_table.products формата:
[{"cost": 674, "product_id": 34}, {"cost": 716, "product_id": 43}]

Код: 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.
CREATE INDEX idxgin ON matrix_table USING GIN (products);
CREATE INDEX idxginp ON matrix_table USING GIN (products jsonb_path_ops);

CREATE OR REPLACE FUNCTION getMatrix() RETURNS TABLE (
	row_id int,
	json_id int,
	product_id int,
	cost int) AS $$
begin
	DECLARE
	row int;
	k int;
	i int;
	result record;

	BEGIN
		FOR row IN (SELECT id FROM matrix_table) LOOP
			i = 0;
			FOR k IN (SELECT json_array_length(products::json) FROM matrix_table WHERE id = row) LOOP
				while i < k LOOP
					FOR row_id, json_id, product_id, cost IN (
						SELECT
							row as row_id,
							i as json_id,
							((products::json->>i)::json->>'product_id')::int as product_id,
							((products::json->>i)::json->>'cost')::int as cost
						FROM matrix_table
						WHERE id = row
					) LOOP
						return next;
					END LOOP;

					i = i + 1;
				END LOOP;
			END LOOP;
		END LOOP;
	END;
end
$$ LANGUAGE plpgsql;



Запросы выполняется не очень быстро.
У меня подозрения что можно сделать быстрее, но пока я не понял как.
...
Рейтинг: 0 / 0
Можно ли оптимизировать данный запрос с json
    #39373172
Melkij
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Andrew B.,

Код: sql
1.
2.
3.
4.
5.
6.
select id as row,
    ordinality as json_id,
    (value->>'product_id')::int as product_id,
    (value->>'cost')::int as cost
from matrix_table
    cross join jsonb_array_elements(products) WITH ORDINALITY


Ничего не забыл?
...
Рейтинг: 0 / 0
Можно ли оптимизировать данный запрос с json
    #39373201
Andrew B.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Фантастика. Процедура стала работать в несколько раз быстрее.

Только join почему-то выполняется почти также долго (он для представления many-to-many отношений):

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
SELECT 
mj.row_id, 
mj.json_id, 
mj.product_id, 
pj.json_id, 
pj.component_id, 
amount, 
cost, 
pj.pname, 
components_table.name

FROM getProductsJson() as pj
JOIN components_table ON pj.component_id = components_table.id
JOIN getMatrixJson() as mj ON pj.row_id = mj.product_id



С индексами gin этот большой запрос выполняется в несколько раз дольше.

Вопрос: если использовать CREATE MATERIALIZED VIEW, то будет ли ускорение при регулярном вызове?
...
Рейтинг: 0 / 0
Можно ли оптимизировать данный запрос с json
    #39373214
Andrew B.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
При этом создание индексов добавляет к поиску 0,1 мсек, вместо ускорения, что весьма странно.
Код: sql
1.
2.
3.
CREATE INDEX matrix_id_idx ON matrix_table (id);
CREATE INDEX products_id_idx ON products_table (id);
CREATE INDEX components_id_idx ON components_table (id);
...
Рейтинг: 0 / 0
Можно ли оптимизировать данный запрос с json
    #39373220
Melkij
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Результат вызова хранимки индексов не предусматривает.
Соответственно переджойнить setof пары хранимок кроме как прямым полным перебором не получится.

Емнип, language sql хранимка из одного выражения может инлайнится в вызывающий запрос и переписаться оптимизатором.
Ещё вам поможет простой view вместо вызова хранимки. Т.к. его оптимизатор тоже переписать сможет для использования некоторых индексов. Если догадается, какие индексы вам нужны.
Или, что очевиднее, целиком переписать задачу, начиная с головы, а не с хвоста и думая, где можно отсеять максимум ненужных строк.
...
Рейтинг: 0 / 0
Можно ли оптимизировать данный запрос с json
    #39373225
Andrew B.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
С хранимыми процедурами стало быстрее на несколько секунд, чем версия из первого поста.
Сейчас попробую без них, ожидаю что станет существенно быстрее.
...
Рейтинг: 0 / 0
Можно ли оптимизировать данный запрос с json
    #39373229
Andrew B.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Скорость получилось точно такая же как с хранимыми процедурами - 15 секунд
...
Рейтинг: 0 / 0
Можно ли оптимизировать данный запрос с json
    #39373286
Melkij
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Странно, вы начали обсуждение производительности запроса и не предъявили ни explain, ни explain (analyze, buffers) ни даже сам запрос.
Я уж не говорю о DDL таблиц.
...
Рейтинг: 0 / 0
Можно ли оптимизировать данный запрос с json
    #39373605
Andrew B.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Melkij,

Код: 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.
CREATE TABLE "matrix_table" (
	"id" INTEGER NOT NULL'',
	"products" UNKNOWN NULL,
	INDEX "" ("id"),
	PRIMARY KEY ("id")
);

CREATE TABLE "products_table" (
	"id" INTEGER NOT NULL'',
	"components" UNKNOWN NULL,
	"name" VARCHAR(255) NOT NULL,
	INDEX "" ("id"),
	PRIMARY KEY ("id")
);

CREATE TABLE "components_table" (
	"id" INTEGER NOT NULL'',
	"name" VARCHAR(255) NOT NULL,
	INDEX "" ("id"),
	PRIMARY KEY ("id")
);

matrix_table example row = id, [{"cost": 674, "product_id": 34}, {"cost": 716, "product_id": 43}]
products_table example row = id, [{"amount": 895, "component_id": 87}, {"amount": 77, "component_id": 51}], name
components_table example row = id, name



1.
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
EXPLAIN (ANALYZE) SELECT mj.row_id, mj.json_id, mj.product_id, pj.json_id, pj.component_id, amount, cost, pj.pname, components_table.name FROM getProductsJson() pj
JOIN components_table ON pj.component_id = components_table.id
JOIN getMatrixJson() mj ON pj.row_id = mj.product_id

"Hash Join  (cost=28.75..128.75 rows=2500 width=90) (actual time=28.169..107.725 rows=266456 loops=1)"
"  Hash Cond: (mj.product_id = pj.row_id)"
"  ->  Function Scan on getmatrixjson mj  (cost=0.25..10.25 rows=1000 width=20) (actual time=11.227..11.988 rows=5173 loops=1)"
"  ->  Hash  (cost=22.25..22.25 rows=500 width=74) (actual time=16.926..16.926 rows=5173 loops=1)"
"        Buckets: 8192 (originally 1024)  Batches: 1 (originally 1)  Memory Usage: 481kB"
"        ->  Hash Join  (cost=3.50..22.25 rows=500 width=74) (actual time=10.259..14.363 rows=5173 loops=1)"
"              Hash Cond: (pj.component_id = components_table.id)"
"              ->  Function Scan on getproductsjson pj  (cost=0.25..10.25 rows=1000 width=52) (actual time=10.152..11.047 rows=5173 loops=1)"
"              ->  Hash  (cost=2.00..2.00 rows=100 width=26) (actual time=0.094..0.094 rows=100 loops=1)"
"                    Buckets: 1024  Batches: 1  Memory Usage: 14kB"
"                    ->  Seq Scan on components_table  (cost=0.00..2.00 rows=100 width=26) (actual time=0.011..0.053 rows=100 loops=1)"
"Planning time: 0.271 ms"
"Execution time: 135.678 ms"



2.
Код: 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.
EXPLAIN (ANALYZE) Select mj.row_id, mj.json_id, mj.product_id, pj.json_id, pj.component_id, amount, cost, pj.pname, components_table.name FROM
(select id as row_id,
        ordinality as json_id,
        (value->>'component_id')::int as component_id,
        (value->>'amount')::int as amount,
        name as pname
     from products_table
        cross join jsonb_array_elements(components) WITH ORDINALITY) pj
JOIN components_table ON pj.component_id = components_table.id
JOIN
(select id as row_id,
        ordinality as json_id,
        (value->>'product_id')::int as product_id,
        (value->>'cost')::int as cost
    from matrix_table
        cross join jsonb_array_elements(products) WITH ORDINALITY) mj
 ON pj.row_id = mj.product_id

"Hash Join  (cost=346.77..46657.78 rows=1020000 width=65) (actual time=9.156..503.600 rows=266456 loops=1)"
"  Hash Cond: (products_table.id = ((jsonb_array_elements_1.value ->> 'product_id'::text))::integer)"
"  ->  Hash Join  (cost=3.25..389.25 rows=10000 width=73) (actual time=0.142..10.818 rows=5173 loops=1)"
"        Hash Cond: (((jsonb_array_elements.value ->> 'component_id'::text))::integer = components_table.id)"
"        ->  Nested Loop  (cost=0.00..211.00 rows=10000 width=51) (actual time=0.044..4.676 rows=5173 loops=1)"
"              ->  Seq Scan on products_table  (cost=0.00..11.00 rows=100 width=720) (actual time=0.013..0.197 rows=100 loops=1)"
"              ->  Function Scan on jsonb_array_elements  (cost=0.00..1.00 rows=100 width=40) (actual time=0.019..0.029 rows=52 loops=100)"
"        ->  Hash  (cost=2.00..2.00 rows=100 width=26) (actual time=0.074..0.074 rows=100 loops=1)"
"              Buckets: 1024  Batches: 1  Memory Usage: 14kB"
"              ->  Seq Scan on components_table  (cost=0.00..2.00 rows=100 width=26) (actual time=0.010..0.035 rows=100 loops=1)"
"  ->  Hash  (cost=216.02..216.02 rows=10200 width=44) (actual time=8.974..8.974 rows=5173 loops=1)"
"        Buckets: 16384  Batches: 1  Memory Usage: 639kB"
"        ->  Nested Loop  (cost=0.00..216.02 rows=10200 width=44) (actual time=0.020..4.803 rows=5173 loops=1)"
"              ->  Seq Scan on matrix_table  (cost=0.00..12.02 rows=102 width=758) (actual time=0.004..0.056 rows=102 loops=1)"
"              ->  Function Scan on jsonb_array_elements jsonb_array_elements_1  (cost=0.00..1.00 rows=100 width=40) (actual time=0.017..0.028 rows=51 loops=102)"
"Planning time: 0.567 ms"
"Execution time: 527.591 ms"
...
Рейтинг: 0 / 0
Можно ли оптимизировать данный запрос с json
    #39373608
Andrew B.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Andrew B.,

В том же порядке.
1. ANALYZE, BUFFERS
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
"Hash Join  (cost=28.75..128.75 rows=2500 width=90) (actual time=31.707..116.717 rows=266456 loops=1)"
"  Hash Cond: (mj.product_id = pj.row_id)"
"  Buffers: shared hit=22"
"  ->  Function Scan on getmatrixjson mj  (cost=0.25..10.25 rows=1000 width=20) (actual time=11.483..12.360 rows=5173 loops=1)"
"        Buffers: shared hit=11"
"  ->  Hash  (cost=22.25..22.25 rows=500 width=74) (actual time=20.200..20.200 rows=5173 loops=1)"
"        Buckets: 8192 (originally 1024)  Batches: 1 (originally 1)  Memory Usage: 481kB"
"        Buffers: shared hit=11"
"        ->  Hash Join  (cost=3.50..22.25 rows=500 width=74) (actual time=11.132..16.923 rows=5173 loops=1)"
"              Hash Cond: (pj.component_id = components_table.id)"
"              Buffers: shared hit=11"
"              ->  Function Scan on getproductsjson pj  (cost=0.25..10.25 rows=1000 width=52) (actual time=11.021..11.968 rows=5173 loops=1)"
"                    Buffers: shared hit=10"
"              ->  Hash  (cost=2.00..2.00 rows=100 width=26) (actual time=0.089..0.089 rows=100 loops=1)"
"                    Buckets: 1024  Batches: 1  Memory Usage: 14kB"
"                    Buffers: shared hit=1"
"                    ->  Seq Scan on components_table  (cost=0.00..2.00 rows=100 width=26) (actual time=0.014..0.045 rows=100 loops=1)"
"                          Buffers: shared hit=1"
"Planning time: 0.301 ms"
"Execution time: 149.220 ms"



2.
Код: 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.
"Hash Join  (cost=346.77..46657.78 rows=1020000 width=65) (actual time=11.930..607.596 rows=266456 loops=1)"
"  Hash Cond: (products_table.id = ((jsonb_array_elements_1.value ->> 'product_id'::text))::integer)"
"  Buffers: shared hit=22"
"  ->  Hash Join  (cost=3.25..389.25 rows=10000 width=73) (actual time=0.207..12.962 rows=5173 loops=1)"
"        Hash Cond: (((jsonb_array_elements.value ->> 'component_id'::text))::integer = components_table.id)"
"        Buffers: shared hit=11"
"        ->  Nested Loop  (cost=0.00..211.00 rows=10000 width=51) (actual time=0.044..5.507 rows=5173 loops=1)"
"              Buffers: shared hit=10"
"              ->  Seq Scan on products_table  (cost=0.00..11.00 rows=100 width=720) (actual time=0.012..0.190 rows=100 loops=1)"
"                    Buffers: shared hit=10"
"              ->  Function Scan on jsonb_array_elements  (cost=0.00..1.00 rows=100 width=40) (actual time=0.021..0.033 rows=52 loops=100)"
"        ->  Hash  (cost=2.00..2.00 rows=100 width=26) (actual time=0.133..0.133 rows=100 loops=1)"
"              Buckets: 1024  Batches: 1  Memory Usage: 14kB"
"              Buffers: shared hit=1"
"              ->  Seq Scan on components_table  (cost=0.00..2.00 rows=100 width=26) (actual time=0.008..0.056 rows=100 loops=1)"
"                    Buffers: shared hit=1"
"  ->  Hash  (cost=216.02..216.02 rows=10200 width=44) (actual time=11.679..11.679 rows=5173 loops=1)"
"        Buckets: 16384  Batches: 1  Memory Usage: 639kB"
"        Buffers: shared hit=11"
"        ->  Nested Loop  (cost=0.00..216.02 rows=10200 width=44) (actual time=0.024..6.241 rows=5173 loops=1)"
"              Buffers: shared hit=11"
"              ->  Seq Scan on matrix_table  (cost=0.00..12.02 rows=102 width=758) (actual time=0.006..0.081 rows=102 loops=1)"
"                    Buffers: shared hit=11"
"              ->  Function Scan on jsonb_array_elements jsonb_array_elements_1  (cost=0.00..1.00 rows=100 width=40) (actual time=0.022..0.036 rows=51 loops=102)"
"Planning time: 0.646 ms"
"Execution time: 639.848 ms"
...
Рейтинг: 0 / 0
Можно ли оптимизировать данный запрос с json
    #39373646
Melkij
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Andrew B.,

ага, оптимизатор заинлайнил подзапросы и результат ухудшился. Ладно, бывает.

Но вам реально надо вычитать всё или всё-таки это какой-то поиск? Вычитать всё, т.е. задача редкая и аналитическая - 0,1с на 260к строк вполне себе результат, на котором можно отстать от pg и заниматься своей аналитикой.
Какой-то поискв реалтайме - то какой? Можно на помощь позвать jsquery, можно понаписать подходящий функциональный индекс. Надо понять, как отсечь максимум неподходящих данных за минимум усилий со стороны субд.
...
Рейтинг: 0 / 0
Можно ли оптимизировать данный запрос с json
    #39373653
Andrew B.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Melkij,

>Но вам реально надо вычитать всё или всё-таки это какой-то поиск?
Пока основная задача это дамп всех json в одну таблицу для переброски в elastic (там нет many-to-many).


>Вычитать всё, т.е. задача редкая и аналитическая - 0,1с на 260к строк вполне себе результат, на котором можно отстать от pg и заниматься своей аналитикой.
Сам запрос выполняется 15,2 - 15,4 секунды и это напрягает.
0,1 это видимо только построение развернутого запроса.

>Какой-то поискв реалтайме - то какой?
Пока поиска нет и врятли с ним будет проблема.

>Надо понять, как отсечь максимум неподходящих данных за минимум усилий со стороны субд.
Все данные нужны для переноса. А вот как переносить только новые данные - это еще один вопрос.
...
Рейтинг: 0 / 0
Можно ли оптимизировать данный запрос с json
    #39373701
Melkij
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Andrew B.,

explain analyze - это время уже с выполнением всего запроса. Построение только плана запроса - цифра Planning time и данные cost или просто explain, без analyze.
Откуда вы наблюдаете 15 секунд?
...
Рейтинг: 0 / 0
Можно ли оптимизировать данный запрос с json
    #39373705
Andrew B.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Melkij,

Если убрать explain, то 15 секунд я наблюдаю справа снизу в окне Query PgAdmin III (ставил отдельно от postgres).
PostgreSQL 9.6.1 on x86_64-pc-linux-gnu, compiled by gcc (Debian 4.9.2-10) 4.9.2, 64-bit.
Elastic при выполнении этого запроса в логах пишет тоже такое большое время.
...
Рейтинг: 0 / 0
Можно ли оптимизировать данный запрос с json
    #39373707
Melkij
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Andrew B.,

А если физически с той же машинки psql'ом? Не с сетью ли у вас проблемы. Explain по понятным причинам не учитывает время на передачу ответа по сети.
...
Рейтинг: 0 / 0
Можно ли оптимизировать данный запрос с json
    #39373717
Andrew B.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Melkij, а да действительно я же подключаюсь к удаленному серверу.
Сейчас проверить скорость на localhost нет возможности, но если explain (analyze) правильно выводит время, поверю ему.

А как тогда быстро передавать данные с сервера на сервер? 260к это же не очень много для сетевого подключения.
...
Рейтинг: 0 / 0
Можно ли оптимизировать данный запрос с json
    #39373769
Melkij
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Andrew B.,

ну вот я и думаю, что с сетью именно проблема. Пакеты по пути слишком часто теряются, ошибки на самом интерфейсе, кто-нибудь хитрый зашейпил канал, MTU неправильно проставлен. Я не сетевик, чтобы точно диагностировать такие вещи. Чтобы точно отвязаться от PG поэкспериментируйте с простой передачей файлов туда-обратно. Если результат будет неадекватно медленный - то спросите в разделе по администрированию куда смотреть и что делать.
...
Рейтинг: 0 / 0
17 сообщений из 17, страница 1 из 1
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Можно ли оптимизировать данный запрос с json
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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