LINUX.ORG.RU

Сообщения polin11

 

Использовать to_tsquery для поиска

Форум — General

Есть строка поиска, хочется сделать полнотекстовой поиск.

to_tsvector(‘simple’::regconfig, «Название») @@ to_tsquery(‘simple’::regconfig, ‘Мое_название’) AND «Название» IS NOT NULL

Но чтобы он работал, нужно удалить невалидные символы из строки поиска (например пробелы из строки поиска), нет ли команды из PGSQL, которая готовит строку для полнотекстового поиска?

 

polin11
()

Вопрос про работу pgAdmin

Форум — General

Использую pgAdimin проверяю обычный запрос SELECT, первый раз выполняется запрос 10 секунд (правильное время время - такое время в реальном приложении), последующее выполнение запроса 0.5 секунд. Может внутри pgAdmin он кэшируется. Приходится перезапускать pgAdmin, переподключаться к серверу. Есть какая-то команда, чтобы pgAdmin выдавал правильный план?

 

polin11
()

Доработать запрос, чтобы не было параллельно выполнения одинаковых запросов

Форум — General

Использую PostgresSQL Есть 2 таблицы autors и documents нужно для определенных аккаунтов обновить информацию в autors по documents.

CREATE TABLE autors (
	id serial PRIMARY KEY,
	author text,
    author_id int not null,
   docs int[]
);
insert into  autors( author, author_id, docs) values 
('Иванов', 3, ARRAY[1,2]),
('Петров', 4,  ARRAY[1,2]),
('Сидоров', 6,  ARRAY[1,2]),
('Сергеев', 5,  ARRAY[1,2]);


CREATE TABLE documents (
	id serial PRIMARY KEY,
	account int not null,
    author_id int not null,
   doc_id int
);
insert into  documents (account, author_id, doc_id) values 
(1,  3, 10),
(1, 4, 24),
(2, 5, 33),
(2, 3, 21);

Запрос:
with au as(
select autors.author_id, array_agg(documents.doc_id) as res
from autors
inner join documents ON (
  autors.author_id = documents.author_id
AND documents.account = ANY(ARRAY[1,2])
)
group by autors.author_id
)

update autors 
set docs = au.res
from au
where autors.author_id  = au.author_id 
returning autors .* 

Стала возникать проблема если например по аккаунту 1, одновременно выполняются несколько одинаковых запросов, падает ошибка deadlock detected.

Хочется перед выполнение запроса как-то понимать, что c этими же аккаунтам выполняется другой запрос, если выполняется, тогда текущий запрос не выполнять, как это можно сделать?

Буду благодарен за конкретный пример

 ,

polin11
()

Ошибки deadlock detected

Форум — General

Использую PGSQL. Есть таблица записей ~ 1000K записей https://www.db-fiddle.com/f/efkuMVy21JWNTE1HyTgYYk/0

CREATE TABLE forms (
	id serial PRIMARY KEY,
	account int not null,
	author text,
    salary int NOT NULL
);
insert into  forms(account, author, salary) values 
(1, 'Иванов', 30),
(1, 'Петров', 40),
(2, 'Сидоров', 40),
(2, 'Сергеев', 50)
Есть запросы с UPDATE, INSERT, DELETE к этой таблице. стали падать ошибки
ERROR: deadlock detected
DETAIL: Process 3415 waits for ShareLock on transaction 1958114794; blocked by process 87442.
Process 87442 waits for ShareLock on transaction 1958114529; blocked by process 3415.
HINT: See server log for query details.
Решил сделать блокировку по аккаунту на 5 секунд
BEGIN ISOLATION LEVEL READ COMMITTED READ WRITE;
SET LOCAL statement_timeout = '5000ms'; 
SELECT PG_ADVISORY_XACT_LOCK("lock_id") FROM (
                SELECT UNNEST('{1100889}'::BIGINT[]) AS "lock_id"
            ) LocksId      
RESET statement_timeout
Это помогло избавиться от deadlock detected, но возникла другая проблема. Если происходят частые вызовы 10 вызовов с интервалом 0.1 секунды для обновления сотрудников из одного аккаунта, то блокировку невозможно создать. Сами запросы сильно не тормозят, пробовал их ускорить по максимуму.

Есть ли какие-нибудь универсальные решения таких проблем? Может кто-то сталкивался, есть общие советы? Можно ли почитать что-нибудь по данному вопросу?

 ,

polin11
()

Прямой обход дерева

Форум — General

Есть словарь, ключ - ид. узла, значение словаря - массив ид. детей у данного узла

{313: [346, 349], 346: [350], 0: [313, 312], 312: [348]}
 
Получается такое n-арное дерево
level 1                    0
level 2           313            312 
level 3     346        349             348     
level 4   350  
  
Нужно сделать прямой обход такого дерева, получить массив словарей, где ключ словаря это ид. узла, а значение словаря уровень иерархии.

Такой результат:

    [{0:1}, {313:2}, {346:3}, {349:3}, {312:2}, {348:3}]
Стал заморачиваться, писать классы для реализации дерева и его обхода, но запутался. Может кто знает более простой алгоритм для реализации, либо библиотеку питона, которую можно использовать

 ,

polin11
()

нужен запрос ORDER BY с NULLS LAST

Форум — General

Есть запрос для PGSQL, нужно сделать аналогичный в SQLite

SELECT name, salary
FROM docs
ORDER BY name NULLS LAST ASC, salary NULL FIRST DESC

в SQLite версии 3.28 нет команды NULLS LAST\FIRST как реализовать для этой версии такой запрос

Пробовал так

SELECT name, salary
FROM docs
ORDER BY name IS NULL ASC, salary IS NOT NULL DESC

в таком случаем NULL значения действительно либо в начале, либо в конце, но сортировка по полям name и salary пропадает (они будут в рандомном порядке).

Аналогично не работает ORDER BY с CASE

 

polin11
()

Написать непростой запрос

Форум — General

Использую СУБД Postgresql, есть таблица

https://www.db-fiddle.com/f/3ERqNCRRXJh5yEJvDtJMQf/0

CREATE TABLE forms (
	id serial PRIMARY KEY,
	account int not null,
	author text,
    doc int NOT NULL,
    users text[]
);

нужно получить результат следующего вида

author : {account: [users]}
insert into  forms(account, author, doc, users) values 
(1, 'Иванов', 3, array['Петя', 'Вася']),
(1, 'Иванов', 3, array['Иван']),
(2, 'Иванов', 3, array['Иван']),
(2, 'Сергеев', 3, array['Павел']),
(2, 'Сергеев', 3, array['Роман']),
(1, 'Сергеев', 3, array['Коля' , 'Дима'])

для предыдущего набора должны получить такой результат

'Иванов': {1: ['Петя', 'Вася', 'Иван'], 2: ['Иван']},
'Сергеев': {1: ['Коля' , 'Дима'], 2: ['Павел', 'Роман']}

Нужно написать запрос, который вернет результат с такой структурой, чтобы потом по минимуму в коде формировать такой словарь.

Нужна конструктивная идея как написать такой запрос

 ,

polin11
()

При update таблицы идет seq scan

Форум — General

Использую Postgresql, есть запрос в котором нужно обновить таблицу новыми значениями, а тех записей которых нет, вернуть.

Приблизительно запрос выглядит так:

WITH ...(
.
.
.),
documents AS (
   SELECT
       ad."DocId"
	   d."EndDate",
	   d."Responsible",
	   d."Account"
   FROM documents_raw d
   LEFT JOIN "ActualDocument" ad
   ON (d."Account"=ad."Account" AND d."Responsible"=ad."Responsible")     
)
documents_upd AS(
   UPDATE "ActualDocument"
   SET "ActualDocument"."EndDate" = documents."EndDate"
   FROM documents
   WHERE "ActualDocument"."DocId"= documents."DocId" 
)
SELECT *
FROM documents_upd
WHERE "DocId" IS NULL

Проблема возникает при обновлении в CTE documents_upd в плане Hash Join идет Seq Scan по таблице «ActualDocument».

Хочется чтобы использовался индекс по первичному ключу «DocId» таблицы «ActualDocument». Например когда использую EXISTS или INNER JOIN в CTE, то используется индекс по первичному ключу «DocId»

WITH (...
.
.
.),
documents AS (
   SELECT
       ad."DocId"
	   d."EndDate",
	   d."Responsible",
	   d."Account"
   FROM documents_raw d
   LEFT JOIN "ActualDocument" ad
   ON (d."Account"=ad."Account" AND d."Responsible"=ad."Responsible")     
)
SELECT *
FROM "ActualDocument"
WHERE EXISTS (
SELECT TRUE
FROM documents
WHERE
"ActualDocument"."DocId"= documents."DocId" 
)

 , ,

polin11
()

Оптимизировать запрос в котором группируется большое кол-во данных

Форум — General

Иcпользую СУБД PostgreSQL

Запрос

 WITH         
		ar AS(
		    SELECT *
		    FROM "ActualDocuments"
		    WHERE 
			"Account" = ANY('{3344433}'::bigint[]) AND
			"MinimalDate" < '2021-09-20'::date 			 
		),      
        user_null AS(
            SELECT
                   DISTINCT
                pp."Account" AS "Account",
                pp."User" AS "Responsible",
                pp."Event" AS "Event",
                array_agg(DISTINCT pp."Subscriber") AS "Subscriber",
                MIN(pp."EndDate") AS "MinimalDate"
            FROM "Documents" pp           
                INNER JOIN ar ON (
			        pp."Account" = ar."Account" AND
				    pp."Event" = ar."Event"
			    )          
            WHERE               
                pp."User" IS NULL                
            GROUP BY pp."Account", pp."User", pp."Event"
        ),
        user_not_null AS(
            SELECT DISTINCT
                pp."Account" AS "Account",
                pp."User" AS "Responsible",
                pp."Event" AS "Event",
                array_agg(DISTINCT pp."Subscriber") AS "Subscriber",
                MIN(pp."EndDate") AS "MinimalDate"
            FROM "Documents" pp         
                INNER JOIN ar ON (
			        pp."Account" = ar."Account" AND
				    pp."Event" = ar."Event"
			    )
            WHERE                
                pp."User" IS NOT NULL                
            GROUP BY pp."Account", pp."User", pp."Event"
        )
		SELECT *
		FROM user_not_null 
		UNION
		SELECT *
		FROM user_null

План

"HashAggregate  (cost=29881.28..29915.65 rows=3437 width=64) (actual time=4117.404..4151.053 rows=107270 loops=1)"
"  Group Key: user_not_null."Account", user_not_null."Responsible", user_not_null."Event", user_not_null."Subscriber", user_not_null."MinimalDate""
"  Buffers: shared hit=735944 dirtied=3, temp read=6722 written=8057"
"  CTE ar"
"    ->  Bitmap Heap Scan on "ActualDocuments"  (cost=36.30..1993.75 rows=465 width=73) (actual time=0.216..1.173 rows=120 loops=1)"
"          Recheck Cond: (("Account" = ANY ('{3344433}'::bigint[])) AND ("MinimalDate" IS NOT NULL))"
"          Filter: ("MinimalDate" < '2021-09-20'::date)"
"          Rows Removed by Filter: 119"
"          Heap Blocks: exact=277"
"          Buffers: shared hit=286"
"          ->  Bitmap Index Scan on "iMinimalDate"  (cost=0.00..36.18 rows=519 width=0) (actual time=0.171..0.172 rows=883 loops=1)"
"                Index Cond: ("Account" = ANY ('{3344433}'::bigint[]))"
"                Buffers: shared hit=9"
"  CTE user_null"
"    ->  HashAggregate  (cost=13603.55..13633.30 rows=2975 width=64) (actual time=1718.383..1718.436 rows=68 loops=1)"
"          Group Key: pp."Account", pp."User", pp."Event", array_agg(DISTINCT pp."Subscriber"), min(pp."EndDate")"
"          Buffers: shared hit=308557 dirtied=3, temp read=3060 written=3080"
"          ->  GroupAggregate  (cost=13484.55..13566.36 rows=2975 width=64) (actual time=710.150..1714.046 rows=68 loops=1)"
"                Group Key: pp."Account", pp."User", pp."Event""
"                Buffers: shared hit=308557 dirtied=3, temp read=3060 written=3080"
"                ->  Sort  (cost=13484.55..13491.99 rows=2975 width=37) (actual time=701.077..778.699 rows=343548 loops=1)"
"                      Sort Key: pp."Account", pp."User", pp."Event""
"                      Sort Method: external merge  Disk: 11032kB"
"                      Buffers: shared hit=308557 dirtied=3, temp read=3060 written=3080"
"                      ->  Nested Loop  (cost=0.56..13312.91 rows=2975 width=37) (actual time=0.037..418.331 rows=343548 loops=1)"
"                            Buffers: shared hit=308557 dirtied=3"
"                            ->  CTE Scan on ar  (cost=0.00..9.30 rows=465 width=12) (actual time=0.001..0.143 rows=120 loops=1)"
"                            ->  Index Scan using "iUserNull" on "Documents" pp  (cost=0.56..28.55 rows=6 width=37) (actual time=0.012..3.119 rows=2863 loops=120)"
"                                  Index Cond: (("Account" = ar."Account") AND ("Event" = ar."Event"))"
"                                  Buffers: shared hit=308557 dirtied=3"
"  CTE user_not_null"
"    ->  Unique  (cost=14101.23..14108.16 rows=462 width=64) (actual time=2247.025..2294.759 rows=107202 loops=1)"
"          Buffers: shared hit=427387, temp read=3662 written=3677"
"          ->  Sort  (cost=14101.23..14102.38 rows=462 width=64) (actual time=2247.023..2260.200 rows=107202 loops=1)"
"                Sort Key: pp_1."Account", pp_1."User", pp_1."Event", (array_agg(DISTINCT pp_1."Subscriber")), (min(pp_1."EndDate"))"
"                Sort Method: external sort  Disk: 8032kB"
"                Buffers: shared hit=427387, temp read=3662 written=3677"
"                ->  GroupAggregate  (cost=14068.07..14080.78 rows=462 width=64) (actual time=1712.571..2077.099 rows=107202 loops=1)"
"                      Group Key: pp_1."Account", pp_1."User", pp_1."Event""
"                      Buffers: shared hit=427387, temp read=2658 written=2673"
"                      ->  Sort  (cost=14068.07..14069.23 rows=462 width=37) (actual time=1712.535..1783.618 rows=237252 loops=1)"
"                            Sort Key: pp_1."Account", pp_1."User", pp_1."Event""
"                            Sort Method: external merge  Disk: 11200kB"
"                            Buffers: shared hit=427387, temp read=2658 written=2673"
"                            ->  Nested Loop  (cost=0.56..14047.62 rows=462 width=37) (actual time=0.258..1412.308 rows=237252 loops=1)"
"                                  Buffers: shared hit=427387"
"                                  ->  CTE Scan on ar ar_1  (cost=0.00..9.30 rows=465 width=12) (actual time=0.218..1.511 rows=120 loops=1)"
"                                        Buffers: shared hit=286"
"                                  ->  Index Scan using "iUser" on "Documents" pp_1  (cost=0.56..30.18 rows=1 width=37) (actual time=0.235..11.441 rows=1977 loops=120)"
"                                        Index Cond: (("Account" = ar_1."Account") AND ("Event" = ar_1."Event"))"
"                                        Buffers: shared hit=427101"
"  ->  Append  (cost=0.00..103.11 rows=3437 width=64) (actual time=2247.028..4050.176 rows=107270 loops=1)"
"        Buffers: shared hit=735944 dirtied=3, temp read=6722 written=8057"
"        ->  CTE Scan on user_not_null  (cost=0.00..9.24 rows=462 width=64) (actual time=2247.027..2320.721 rows=107202 loops=1)"
"              Buffers: shared hit=427387, temp read=3662 written=4678"
"        ->  CTE Scan on user_null  (cost=0.00..59.50 rows=2975 width=64) (actual time=1718.393..1721.813 rows=68 loops=1)"
"              Buffers: shared hit=308557 dirtied=3, temp read=3060 written=3379"
"Planning time: 0.961 ms"
"Execution time: 4164.426 ms"

Для некоторых аккаунтов получается большое количество записей, которые нужно сгруппировать, из-за этого запрос долго выполняется по времени и shared hit memory. У меня идей не осталось

 ,

polin11
()

Индекс для UUID

Форум — General

Использую Postresql.

Есть таблица Documents с полями:

Account тип bigint Document тип bigint

User тип UUID

Есть 2 индекса

CREATE INDEX "AccountDocument" ON "Documents" USING btree ("Account" NULLS LAST, "Document" NULLS LAST)
WHERE ("Account" IS NOT NULL OR "Document" IS NOT NULL);
CREATE INDEX "AccountUserDocument" ON "Documents"  USING btree ("Account", "User", "Document")

Для простого запроса хочу, чтобы использовался индекс AccountUserDocument

SELECT *
FROM "Documents"
WHERE "Account" = 1
AND "USER" = 'dd758b54-55b3-442a-804b-8a3d311432ba'::UUID 
AND "Document" = 2
но используется индекс AccountDocument
"Index Scan using "AccountDocument" on "Documents"  (cost=0.29..8.31 rows=1 width=73) (actual time=0.016..0.016 rows=0 loops=1)"
"  Index Cond: ("Document" = 2)"
"  Filter: (("Account" = 1) AND ("USER" = 'dd758b54-55b3-442a-804b-8a3d311432ba'::uuid))"
"  Buffers: shared hit=2"
"Planning time: 1.026 ms"
"Execution time: 0.039 ms"
только есть указать у индекса AccountUserDocument тип индекса gist, то он используется
"Index Scan using "AccoutUserDocument" on "Documents"  (cost=0.28..8.30 rows=1 width=73) (actual time=3.626..3.626 rows=0 loops=1)"
"  Index Cond: (("User" = 'dd758b54-55b3-442a-804b-8a3d311432ba'::uuid) AND ("Document" = 2))"
"  Filter: ("Account" = 1)"
"  Buffers: shared hit=73"
"Planning time: 0.946 ms"
"Execution time: 3.652 ms"
Почитал инфу про тип gist он обычно используется для полнотекстового поиска.

Вопрос почему индекс не используется с типом btree, только из-за того, что в индексе есть поле UUID?

 , ,

polin11
()

Проблема импорта функций в PYTHON, если папка и файл называются одинаково

Форум — General

Есть файл data_export.py и папка data_export в которой лежит файл data_export_expanded.py

folder_name\data_export.py

folder_name\data_export\data_export_expanded.py

мне нужно импортировать в PYTHON func_name1 из data_export.py и func_name2 из data_export_expanded.py

Пробую импортировать

from folder_name.data_export import func_name1

from folder_name.data_export.data_export_expanded import func_name2

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

 ,

polin11
()

ERROR: tuple concurrently updated в чем проблема?

Форум — General

Использую СУБД Postgresql, Есть запрос, при помощи него получаю записи в которых значение поля «Person» (поле текстового формата) невозможно привести в типу UUID


 CREATE OR REPLACE FUNCTION uuid_or_null(str text)
           RETURNS uuid AS $$
           BEGIN
                 RETURN str::uuid;
           EXCEPTION WHEN invalid_text_representation THEN
                 RETURN NULL;
           END;
           $$ LANGUAGE plpgsql;
   
             SELECT DISTINCT "Id", "Person"
           FROM "Document"
           WHERE "Person" IS NOT NULL AND uuid_or_null("Person") IS NULL  

Возникла проблема с 1 БД (на двух других БД без ошибок), падает ошибка tuple concurrently updated в чем проблема не могу разобраться?

 

polin11
()

Получить строки, которые нельзя привести к UUID

Форум — General

Иcпользую СУБД Postgresql, поле у таблицы типа text, в нем могут быть UUID в виде строки, либо произвольные строки

например

‘033d111a-d046-4dcc-8beb-0f074a4b12r3’

‘jdfhfhfhfhfhfhfhfh’

‘1801b6a3-2b7b-429a-ada8-f54c5b00ee87’

Мне нужно написать запрос и достать записи, где обычные строки, а не строки вида UUID, возможно ли это сделать?

 ,

polin11
()

ERROR: out of memory

Форум — General

Использую СУБД Postgresql, пытаюсь вставить 176 000 записей в таблицу, падает ошибка

Ошибка выполнения SQL команды: ERROR: out of memory DETAIL: Failed on request of size 33554321

Подскажите какую настройку PG сервера посмотреть и как изменить, чтобы ошибка не падала?

 

polin11
()

Долгое удаление записей из связанной таблицы

Форум — General

Есть таблица Document (5 млн. записей) и связанная таблица DocumentLinks (35 млн. записей) связь 1-М (один ко многим), у таблицы DocumentLinks поля Id, IdLink, DocumentId, DocumentLink все они связаны с первичным ключом из таблицы Document.

При удалении записей из таблицы Document каскадно удаляются связанные записи из DocumentLinks - это происходит очень долго (одна запись удаляется 6 сек.), даже в том случае когда связанных записей нет в DocumentLinks. Индексы созданы по всем полям Id, IdLink, DocumentId, DocumentLink.

"Delete on "Document"  (cost=0.42..8.44 rows=1 width=6) (actual time=0.043..0.043 rows=0 loops=1)"
"  Buffers: shared hit=6"
"  ->  Index Scan using "iDocument-FullCode" on "Document"  (cost=0.42..8.44 rows=1 width=6) (actual time=0.026..0.027 rows=1 loops=1)"
"        Index Cond: ("FullCode" = '2021'::text)"
"        Buffers: shared hit=4"
"Planning time: 0.941 ms"
"Trigger for constraint rDocumentLinks-Id: time=8.784 calls=3"
"Trigger for constraint rDocumentLinks-IdLink: time=59818.664 calls=3"
"Trigger for constraint rDocumentLinks-DocumentId: time=51.304 calls=3"
"Trigger for constraint rDocumentLinks-DocumentLink: time=24.373 calls=3"
"Execution time: 60018.958 ms"

Вопрос как можно ускорить удаление записей?

 ,

polin11
()

быстрый Nested Loop и медленный Merge join

Форум — General

Использую PostgreSQL, есть иерархическая таблица Document, есть простой рекурсивный запрос, получаем записи вниз по иерархии, поле иерархии Hier

 WITH RECURSIVE DOWN AS( 
           SELECT s.* 
           FROM "Document" s 
           WHERE "Hier" =  1123
           UNION 
           SELECT s1.* 
           FROM DOWN 
           INNER JOIN "Document" s1 ON s1."Hier"= DOWN."@Document" 
         ) 
         SELECT * 
         FROM DOWN 

На одной БД планировщик использует Nested Loop запрос выполняется быстро

"CTE Scan on down  (cost=229320.82..231171.20 rows=92519 width=253) (actual time=0.207..2.038 rows=17 loops=1)"
"  Buffers: shared hit=62 read=3"
"  CTE down"
"    ->  Recursive Union  (cost=0.43..229320.82 rows=92519 width=272) (actual time=0.202..2.005 rows=17 loops=1)"
"          Buffers: shared hit=62 read=3"
"          ->  Index Scan using "iDocument-Hier" on "Document" s  (cost=0.43..27.52 rows=9 width=272) (actual time=0.194..0.203 rows=4 loops=1)"
"                Index Cond: ("Hier" = 4634473)"
"                Buffers: shared hit=7 read=1"
"          ->  Nested Loop  (cost=0.43..22744.29 rows=9251 width=272) (actual time=0.831..0.870 rows=6 loops=2)"
"                Buffers: shared hit=55 read=2"
"                ->  WorkTable Scan on down down_1  (cost=0.00..1.80 rows=90 width=8) (actual time=0.001..0.008 rows=8 loops=2)"
"                ->  Index Scan using "iDocument-Hier" on "Document" s1  (cost=0.43..251.66 rows=103 width=272) (actual time=0.096..0.098 rows=1 loops=17)"
"                      Index Cond: ("Hier" = down_1."@Document")"
"                      Buffers: shared hit=55 read=2"
"Planning time: 1.200 ms"
"Execution time: 3.596 ms"

На другой БД с примерно теми же данными используется Merge Join и запрос выполняется очень долго и много ресурсов использует

"CTE Scan on down  (cost=14385858.75..16871148.97 rows=124264511 width=253) (actual time=7.388..54128.588 rows=17 loops=1)"
"  Buffers: shared hit=562520 read=190529"
"  CTE down"
"    ->  Recursive Union  (cost=0.56..14385858.75 rows=124264511 width=277) (actual time=7.383..54128.547 rows=17 loops=1)"
"          Buffers: shared hit=562520 read=190529"
"          ->  Index Scan using "iDocument-Hier" on "Document" s  (cost=0.56..1610.97 rows=581 width=277) (actual time=7.373..9.128 rows=4 loops=1)"
"                Index Cond: ("Hier" = 939969)"
"                Buffers: shared read=7"
"          ->  Merge Join  (cost=480.01..1189895.76 rows=12426393 width=277) (actual time=27057.258..27059.673 rows=6 loops=2)"
"                Merge Cond: (s1."Hier" = down_1."@Document")"
"                Buffers: shared hit=562520 read=190522"
"                ->  Index Scan using "iDocument-Hier" on "Document" s1  (cost=0.56..986143.92 rows=6750595 width=277) (actual time=0.706..26652.712 rows=2957380 loops=2)"
"                      Buffers: shared hit=562520 read=190522"
"                ->  Sort  (cost=479.45..493.98 rows=5810 width=8) (actual time=0.034..0.040 rows=11 loops=2)"
"                      Sort Key: down_1."@Document""
"                      Sort Method: quicksort  Memory: 25kB"
"                      ->  WorkTable Scan on down down_1  (cost=0.00..116.20 rows=5810 width=8) (actual time=0.003..0.004 rows=8 loops=2)"
"Planning time: 1.677 ms"
"Execution time: 54145.287 ms"

В обеих базах есть индекс по полю Hier, пробовал выполнить vacuum analyze, reindex, обновить статистику для планировщика - ничего не помогает.

Как решить проблему на второй базе, заставить планировщик использовался Nested Loop?

 ,

polin11
()

Создать индекс для рекурсивного запроса

Форум — General

Иcпользую PostreSQL, есть рекурсивный запрос в таблице Document для получение записей вниз по иерархии, идентификатор в таблице @Document. Поле Hierarchy ссылка на идентификатор родительской записи.

EXPLAIN (ANALYZE,BUFFERS)
        WITH  RECURSIVE 
                hier_down AS(
                    SELECT
                       h."@Document",
                       h."Hierarchy",
                       h."Hint"
					   FROM "Document" h
                       WHERE
                          "@Document" = 13
                    UNION all
                    SELECT
                        "Document" ."@Document",
                         "Document" ."Hierarchy",
                         "Document"."Hint"
                    FROM hier_down, "Document" 
                    WHERE   "Document"."Hierarchy" =  hier_down."@Document"
                )
SELECT *
FROM hier_down

План выполнения запроса:

"CTE Scan on hier_down  (cost=783.59..861.41 rows=3891 width=44) (actual time=0.008..0.748 rows=5 loops=1)"
"  Buffers: shared hit=281"
"  CTE hier_down"
"    ->  Recursive Union  (cost=0.28..783.59 rows=3891 width=76) (actual time=0.007..0.745 rows=5 loops=1)"
"          Buffers: shared hit=281"
"          ->  Index Scan using "pDocument" on "Document" h  (cost=0.28..8.29 rows=1 width=76) (actual time=0.006..0.006 rows=1 loops=1)"
"                Index Cond: ("@Document" = 13110)"
"                Buffers: shared hit=3"
"          ->  Hash Join  (cost=0.33..69.75 rows=389 width=76) (actual time=0.044..0.143 rows=1 loops=5)"
"                Hash Cond: ("Document"."Hierarchy" = hier_down_1."@Document")"
"                Buffers: shared hit=278"
"                ->  Seq Scan on "Document"  (cost=0.00..62.66 rows=766 width=76) (actual time=0.003..0.061 rows=766 loops=5)"
"                      Buffers: shared hit=275"
"                ->  Hash  (cost=0.20..0.20 rows=10 width=4) (actual time=0.002..0.002 rows=1 loops=5)"
"                      Buckets: 1024  Batches: 1  Memory Usage: 9kB"
"                      ->  WorkTable Scan on hier_down hier_down_1  (cost=0.00..0.20 rows=10 width=4) (actual time=0.000..0.000 rows=1 loops=5)"
"Planning time: 0.336 ms"
"Execution time: 0.786 ms"

Хочется избавиться от seq scan Есть индекс по полю Hierarchy - он не используется Есть составной индекс (Hierarchy, @Document ) - он не используется

сделал индекс

CREATE INDEX "Hier"
ON "Document" USING btree
("Hierarchy" NULLS LAST, "@Document" NULLS LAST, "Hint" NULLS LAST);
он используется, но перестает использоваться когда добавляется новое поле в SELECT, приходится добавлять новое поле в индекс.

Как бы создать индекс, на который не влиял бы набор полей в SELECT?

 ,

polin11
()

Создать табличку при помощи unnest

Форум — General

Использую СУБД Postgresql, unnest для создания временной таблицы

 SELECT UNNEST('{"10","20"}'::varchar[]) "Ключ",
                   UNNEST('{103,101}'::bigint[]) "Документ"

Получаю таблицу из 2 столбцов Ключ и Документ к которым можно обращаться, нужно добавить еще один столбец Массив
            SELECT UNNEST('{"10","20"}'::varchar[]) "Ключ",
                   UNNEST('{103,101}'::bigint[]) "Документ",
                   UNNEST(ARRAY[1,3], ARRAY[4,5]) "Массив"

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

 

polin11
()

Помощь в изменении структуры БД

Форум — General

Использую PostgreSQL 11.

Есть таблица USERS 2 млн. записей

 
CREATE TABLE USERS (
  id INT NOT NULL,
  name VARCHAR(30) NOT NULL
);
INSERT INTO USERS 
    (id, name) 
VALUES 
    (1,'John'),
    (2,'Mike'),
    (3,'John');

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

CREATE TABLE LINKS (
  id INT NOT NULL,
  id_rec INT NOT NULL,
  id_link INT NOT NULL
);
INSERT INTO LINKS 
    (id, id_rec, id_link) 
VALUES 
    (1,1, 2),
    (2,1,3),
    (3,1, 4); 

Причем связь односторонняя, то есть связей всего 5000, к которым привязаны от 2 записей до 2 млн. записей, Джойнить эти 2 таблицы стало сложно, долго по времени и по ресурсам.

Хочу узнать мнения по оптимальному изменению структуры таблиц, может быть сделать таблицу на 5000 связей, которым указать идентификаторы в виде массива.

Может кто-то сталкивался с похожей проблемой?

 

polin11
()

Выполнить запрос 1 раз, но получать записи по кускам

Форум — General

Использую PostgreSQL, есть большая таблица несколько миллионов записей, для примера

CREATE TABLE towns ( id INTEGER PRIMARY KEY, name CHARACTER VARYING(30), root INTEGER );

INSERT INTO towns VALUES (1, ‘Berlin’, 1);

INSERT INTO towns VALUES (2, ‘Rome’, 2);

INSERT INTO towns VALUES (3, ‘Paris’, 1);

INSERT INTO towns VALUES (1, ‘Turin’, 2);

Нужно используя курсоры в Postgresql написать запрос, получить все записи отсортированные по root, выполнить запрос 1 раз, а получать по значению root

https://postgrespro.ru/docs/postgres...lpgsql-cursors

 ,

polin11
()

RSS подписка на новые темы