powered by simpleCommunicator - 2.0.53     © 2025 Programmizd 02
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Postgres не хочет юзать память
25 сообщений из 75, страница 1 из 3
Postgres не хочет юзать память
    #39462988
an2k
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
При выполнении сложных запросов, массовых заливок Postgres жутко тормозит.
Почитал рекомендации пошаманил в postgresql.conf (прилагаю).
Ничего не дает - по прежнему загрузка ЦП 100%, загрузка памяти 3%

Куды копать?
Может вовсе не postgres виноват, а Линукс?
...
Рейтинг: 0 / 0
Postgres не хочет юзать память
    #39463042
qwwq
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
an2kПри выполнении <>, массовых заливок Postgres жутко тормозит.

предположим СУБД вместо того чтобы залить данные на диск (поюзать дисковую) поюзало память. и туточки всё упало (где-то там перемкнуло в БП или обоих, или даже на мамке бумкнуло) -- и оно так в памяти и сдохло, не попав на диск -- оно вам надо ?

ну и про запросы: -- какие запросы ?
тексты, планы, вот это всё -- где оно ?

то, что 100 % проца -- может означать, что запросы вычислительно дорогие, например, а память им нахер не упала.
...
Рейтинг: 0 / 0
Postgres не хочет юзать память
    #39463064
an2k
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Вот функция
Код: 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.
-- ОЧИСТКА ТАБЛИЦЫ log_write ОТ ДУБЛИРУЮЩИХ СТРОК

CREATE or replace FUNCTION f_delete_notmax() RETURNS integer
    LANGUAGE plpgsql
    AS $$
DECLARE
_rec1 record  ;
_rec2 record  ;
_rec_id integer := 0  ;
_max_id integer := 0  ;
_table_name varchar(32) ;
BEGIN

for _rec1 in
    select distinct lw_table_name from log_write
loop
    _table_name = _rec1.lw_table_name ;
    if _table_name != 'schedules' then
        RAISE NOTICE 'table_name: %', _table_name;

        for _rec2 in
            EXECUTE 'select lw_rec_id, max(log_write.id) as max_id
            from log_write
            where lw_table_name = ' || quote_literal( _table_name ) ||
            'group by lw_rec_id'
        loop
            _rec_id = _rec2.lw_rec_id ;
            _max_id = _rec2.max_id ;

            EXECUTE 'delete from log_write
            where id<' || _max_id ||
                ' and lw_rec_id = ' || _rec_id ||
                ' and lw_table_name = ' || quote_literal( _table_name );
        end loop;
    end if;
end loop;

delete from log_write where lw_table_name='schedules' ;

return 1 ;

END;
$$ security definer ;



Вот ее вызов:

Код: sql
1.
select * from f_delete_notmax(); -- собственно чистка log_write


на таблице размером 20 млн. записей зависает на сутки.

План посоветуйте как посмотреть, плз.
...
Рейтинг: 0 / 0
Postgres не хочет юзать память
    #39463103
qwwq
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
an2k,

осторожно поинтересуюсь:

1 скока дистинктных lw_table_name вы ожЫдаете наблюсть в вашей log_write ?

и
2. есть ли индекс на log_write, начинающийся с lw_table_name , (но, упаси, не богомерзкий текст/варчар_паттерн_опс, а нормально поддерживающий поиск правых/левых ветвей )

фак ультативнои да, похоже вашу задачу писали дятелы на оть@бись, а не для того, чтобы она таки нормально решалась (я бы, наверное, делал её короткими частями, скорее всего, и , возможно, даже в параллель по диапазонам lw_table_name, с небольшой опорной табличкой лога отработанных ключей )
...
Рейтинг: 0 / 0
Postgres не хочет юзать память
    #39463111
qwwq
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
an2kПлан посоветуйте как посмотреть, плз.
Код: sql
1.
explain analyze select distinct lw_table_name from log_write ;


но это неинтересно

интересно что--нть типа

Код: sql
1.
2.
3.
4.
5.
6.
7.
deallocate all;
PREPARE foo (text) AS 
select lw_rec_id, max(log_write.id) as max_id
            from log_write
            where lw_table_name = $1
            group by lw_rec_id;
EXPLAIN ANALYZE EXECUTE foo('any_name');


ну и т.п.
хотя и оно не интересно, ибо, имхо, нехрен реализовывать ваш скрипт как он есть вообще.

пс. а конкурирующие читатели писатели у вас имеются ? эдак вы ещё можете всё время в очередь вставать за оными.
...
Рейтинг: 0 / 0
Postgres не хочет юзать память
    #39463322
an2k
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
qwwq,

1. Около 30


2.

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
\d log_write
                                      Таблица "public.log_write"
    Колонка    |             Тип             |                      Модификаторы                      
---------------+-----------------------------+--------------------------------------------------------
 id            | integer                     | NOT NULL DEFAULT nextval('log_write_id_seq'::regclass)
 lw_source_id  | integer                     | 
 lw_table_name | character varying(64)       | 
 lw_rec_id     | integer                     | 
 lw_op_code    | character varying(3)        | 
 lw_datetime   | timestamp without time zone | 
Индексы:
    "log_write_pkey" PRIMARY KEY, btree (id)
    "lw_op_code" btree (lw_op_code)
    "lw_rec_id" btree (lw_rec_id)
    "lw_source_id" btree (lw_source_id)
    "lw_table_name" btree (lw_table_name)
...
Рейтинг: 0 / 0
Postgres не хочет юзать память
    #39463324
an2k
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
qwwq,
3.
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
explain analyze select distinct lw_table_name from log_write ;

                                                          QUERY PLAN                                                          
------------------------------------------------------------------------------------------------------------------------------
 HashAggregate  (cost=249019.88..249020.07 rows=19 width=13) (actual time=8767.140..8767.154 rows=32 loops=1)
   Group Key: lw_table_name
   ->  Seq Scan on log_write  (cost=0.00..234526.10 rows=5797510 width=13) (actual time=0.083..4783.462 rows=5450990 loops=1)
 Planning time: 0.709 ms
 Execution time: 8767.513 ms
(5 строк)



4.
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
deallocate all;
PREPARE foo (text) AS 
select lw_rec_id, max(log_write.id) as max_id
            from log_write
            where lw_table_name = $1
            group by lw_rec_id;
EXPLAIN ANALYZE EXECUTE foo('any_name');

                                                              QUERY PLAN                                                               
---------------------------------------------------------------------------------------------------------------------------------------
 HashAggregate  (cost=38389.38..38437.01 rows=4763 width=8) (actual time=0.161..0.161 rows=0 loops=1)
   Group Key: lw_rec_id
   ->  Index Scan using lw_table_name on log_write  (cost=0.56..38327.78 rows=12320 width=8) (actual time=0.119..0.119 rows=0 loops=1)
         Index Cond: ((lw_table_name)::text = 'any_name'::text)
 Execution time: 0.360 ms
(5 строк)



Не могли бы прокомментировать этот результат?

PS: Конкурирующих читателей/писателей нет.
...
Рейтинг: 0 / 0
Postgres не хочет юзать память
    #39463344
qwwq
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
an2k,
вы всё ещё настаиваете на удалении 20лямов (хотя в плане у вас всего 5.5лямов) записей 1--й транзакцией ?


если да -- то это
1. делается одним запросом.(напишите этот запрос [используйте кляузу USING для набора оставляемых записей] и посмотрите на его план)
//и еще думаю, не помог бы вам тут, часом, индекс (lw_table_name,lw_rec_id,id). не совсем ясно, что у вас с плотностью lw_rec_id -- для получения max(id) по группам и самих групп для using

2. или за один проход for loop по сортированному набору. (факультативно, тут скорее всего это не интересно)
Код: plaintext
ORDER BY lw_table_name , lw_rec_id [, id DESC ]
//один раз тратитесь на сорт, а удаляете позаписно по id или по ctid

немного оффтопапо вашей процедуре:
есть ли у вас таблица "имен таблиц" ? если да, зачем вы упираетесь с дистинктом ? (он конечно сутки не занимает, но все ж таки лишняя работа).

или ознакомьтесь с loose-indexcan--ом. тоже вариант. в вашем случае он (дистинкт) вообще может быть for loop-ом по одной записи, следующей вдоль индекса lw_table_name. (SELECT lw_table_name INTO _lw_table_name FROM mytable WHERE lw_table_name >_lw_table_name ORDER BY lw_table_name LIMIT 1).

и да: не налегайте на динамический sql там, где планируете 10-ки тысяч синтаксических разборов.
...
Рейтинг: 0 / 0
Postgres не хочет юзать память
    #39463347
Павел Лузанов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
an2k, так не пробовали?
Код: sql
1.
2.
3.
4.
5.
6.
delete from log_write
where (lw_table_name, lw_rec_id, id) not in (
   select lw_table_name, lw_rec_id, max(id)
   from   log_write
   group by lw_table_name, lw_rec_id
);
...
Рейтинг: 0 / 0
Postgres не хочет юзать память
    #39463350
qwwq
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Павел Лузанов,

вот,да. можно и без using.
...
Рейтинг: 0 / 0
Postgres не хочет юзать память
    #39463378
ursido
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
an2k,

А сколько в штуках строк остается?

Может, сделать наоборот:
1. Выбрать остающиеся строки во временную таблицу
2. Очистить имеющуюся таблицу (truncate)
3. Вставить остающиеся записи в таблицу из временной.
...
Рейтинг: 0 / 0
Postgres не хочет юзать память
    #39463394
qwwq
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ursido,

это работает если нет конкурентных обращений к табличке.
можно это же сделать без времянок:
-- создаем 2 ротируемые партиечки. можно с триггером before insert [с перегружаемым тестом ф-ии] подстановки номера рабочей партиции на пустом предке, но обычно дешевле с подстановкой имен на уровне хранимок вставки, если обработка в основном массовая )
обеспечиваем лок записи о рабочей партиции на момент ротации. (т.е. очередь, и строгую одномоментность). и переключаем партиции.
после переключения рабочей партиции делаем сдвиг оставляемых записей
что-то типа:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
WITH del AS -- удаление из старой партиции
(delete FROM log_write_1 -- подстановка имени старой партиции
WHERE 
lw_table_name, lw_rec_id, id IN 
(
select lw_table_name, lw_rec_id, max(id) AS id
   from   log_write
   group by lw_table_name, lw_rec_id
RETURNING *
)
INSERT INTO log_write_2 -- подстановка имени новой партиции
 SELECT * FROM del -- вставка только что удаленных 
                             --в новую рабочую партицию
;
-- и окончательно
truncate log_write_1;


-- в любой момент табличка--предок доступна для чтения (с точностью до лока потомка на момент транкейта [тут можно выводить потомка из иерархии, что м.б. быстрее транкейта. но это чревато ошибкой в уже спланированных и выполняющихся запросах] )
накладные -- куча хенджоба. и усложнение планов запросов к таблице
выигрыш -- снятие проблем вакуумирования и перестройки индексов при массовой очистке
...
Рейтинг: 0 / 0
Postgres не хочет юзать память
    #39463405
ursido
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
qwwq,

То что Вы описали сильно напоминает механизм ротации очередей Londiste. Имеет смысл посмотреть их реализацию.
...
Рейтинг: 0 / 0
Postgres не хочет юзать память
    #39463471
an2k
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
All,

Прошу прощения, я не сказал в чем смысл:

В базе несколько таблиц:
Студенты
Преподаватели
Оценки

Они в течении времени могут меняться (исправление опечатки в ФИО, изменение оценки, etc.)

Все эти изменения (включая первичный insert) фиксировались в таблице log_write для того, чтобы другие системы могли периодически получать из этой базы только изменившиеся (или новые) данные.

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

До сих пор в log_write хранились все изменения, теперь решено оставить только последние, а все неактуальные удалить. Всего их было 20 млн. остаться должно 5-6.

Т.е. необходимо удалить из таблицы log_write все записи, оставив по одной для каждого уникального значения поля lw_table_name, притом с наибольшим для этого значения id.
...
Рейтинг: 0 / 0
Postgres не хочет юзать память
    #39463582
an2k
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Павел Лузанов,

Попробовал. После трех часов работы остановил.
Более быстрого способа не придумать?
...
Рейтинг: 0 / 0
Postgres не хочет юзать память
    #39463583
an2k
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ursido,

хорошая идея, но сломал голову, как выбрать только строки с максимальным id
или не выспался или голову на свалку ((
...
Рейтинг: 0 / 0
Postgres не хочет юзать память
    #39463590
ursido
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
an2k,

Мне кажется, Вам нужно остановиться и собраться с мыслями.
Эта задача написана в темах выше уже несколько раз.

Как соберетесь с мыслями, смотрите (скопировано из поста выше 20528831 ):

Код: sql
1.
2.
3.
select lw_table_name, lw_rec_id, max(id)
   from   log_write
   group by lw_table_name, lw_rec_id

...
Рейтинг: 0 / 0
Postgres не хочет юзать память
    #39463606
qwwq
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
an2kПавел Лузанов,

Попробовал. После трех часов работы остановил.
Более быстрого способа не придумать?
покажите
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
EXPLAIN ANALYZE
delete from log_write
where
  lw_table_name = 'any_lw_table_name'
  AND (lw_table_name, lw_rec_id, id) not in (
   select lw_table_name, lw_rec_id, max(id)
   from   log_write
   where lw_table_name='any_lw_table_name'
   group by lw_table_name, lw_rec_id
);


для какого-нить существующего 'any_lw_table_name', но не самого частого. чтобы уложжиться. и следите за состоянием соединения через pg_stat_activity. т.к. в задаче, как она поставлена, все время присутствуют конкурирующие обращения. (в логируемые таблы кто--то пишет и переписывает)
...
Рейтинг: 0 / 0
Postgres не хочет юзать память
    #39463622
ursido
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
qwwq,

По постановке задачи от таблицы должно остаться примерно 25% записей. Вариант с удалением вызывает тоску.

Предлагаю следующее действие:

Выбираем строки, которые нужно оставить. Среди них фиксируем самую раннюю дату. Теперь все строки в таблице, более ранние чем зафиксированная дата, можно удалять по дате.

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

не спешите.
я хочу увидеть план.
а в нем отсутствие триггеров.
удалить 20 лямов узких рекордов -- это как кот чихнул.
если ничто не мешает.
в последнем я сильно сомневаюсь.

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

как вариант -- удалять запись--писи в исходной хранимке ТС (вернее её аналога с прямым проходом по сортированному набору) можно автономно через дблинк. это сильно развязывает руки. плюс нарезать головной процесс на слайсы минут по 10--20, посредство statement_timeout для выделенного ползателя. во избежание излишне долгой транзакции. и не надо никаких ротаций. но перестраивать индексы пж-у придётся долго и упорно.
...
Рейтинг: 0 / 0
Postgres не хочет юзать память
    #39463654
ursido
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
qwwq,

Я не смогу его потом развидеть.

В предложенном Вами запросе имеются:

-- Группировка по полям без индекса с составными полями (нет индекса, под эту группировку)
-- Предложение NOT IN (SELECT ...)

Причем эти действия равномерно размазаны между отдельными группами (этих групп со слов автора примерно 5-6 млн).

Какие еще более медленные запросы Вы знаете?
...
Рейтинг: 0 / 0
Postgres не хочет юзать память
    #39463658
ursido
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
qwwq,

И еще напомню, что прямо сейчас автовакуум отключен. (Надеюсь, только на период интенсивной обработки данных).
...
Рейтинг: 0 / 0
Postgres не хочет юзать память
    #39463678
qwwq
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ursidoqwwq,

Я не смогу его потом развидеть.

В предложенном Вами запросе имеются:

-- Группировка по полям без индекса с составными полями (нет индекса, под эту группировку)
-- Предложение NOT IN (SELECT ...)

Причем эти действия равномерно размазаны между отдельными группами (этих групп со слов автора примерно 5-6 млн).

Какие еще более медленные запросы Вы знаете?
вам же ТС отписался, что это займет примерно Execution time: 8767.513 ms

если так боитеся что NOT IN (SELECT ...) распишите его через
Код: sql
1.
2.
3.
4.
5.
WITH mater AS (SELECT .....)
DELETE ... FROM .... 
WHERE .... 
and NOT EXISTS(SELECT 1 FROM mater
                            WHERE ....) 

это механическая работа

или даже через что--то навроде:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
WITH mater AS (SELECT .....)
DELETE ... FROM ....  t
using mater m
WHERE 
m.k1=t.k1
AND m.k2=t.k2
AND m.id>t.id
AND ...

это ТОЖЕ механическая работа
вы, как минимум, навяжете однократную материализацию (хотя она и так там д.б. однократной)

думаю проблема не в том , чтобы просканировать и сгруппировать всю табличку [Execution time: 8767.513 ms ], а в том, что где--то что--то во что--то упирается.

варианты --
триггера (в т.ч. констрайнтовые)
или локи конкурентов.

пока не узнаем -- дальше не ясно.
...
Рейтинг: 0 / 0
Postgres не хочет юзать память
    #39463688
ursido
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Да. Ждем ответа от автора.

Пока продолжим:
qwwq...
вам же ТС отписался, что это займет примерно Execution time: 8767.513 ms
...


И это время (8 секунд) будет затрачено на подзапрос для каждой из строк, которых 20 млн. По-моему тормозилово именно здесь (то есть во вложенном подзапросе)
...
Рейтинг: 0 / 0
25 сообщений из 75, страница 1 из 3
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Postgres не хочет юзать память
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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