
Yaroslav
20.07.2018
10:46:43

Oleg
20.07.2018
10:47:17
файлы клиенту как файлы надо возвращать?

Ilia
20.07.2018
10:48:56

Maksim
20.07.2018
10:49:37
Оффтоп, просто в инете ничего не выдает. Есть ли чат для фотолюбителей?

Google

Sasha
20.07.2018
10:49:38
это уже другой вопрос. (ну например много томов Война и Мир :))

Fike
20.07.2018
10:56:42

Oleg
20.07.2018
11:03:00
@Sashka_S варианты:
хранить файлы как файлы на файловой системе файлсервера. в хранилке "путь к файлу и имя файла" - идентифицирует документ, все его метаданные например в реляционной базе. FTS прикручивать сбоку.
хранить файлы как чанки размазанные по кластеру. ну типа хадуп. вот кстати https://events.yandex.ru/lib/talks/524/

Quantum Harmonizer
20.07.2018
11:19:16
@Komzpa

Aleksander
20.07.2018
11:20:24
уже потер

Radim
20.07.2018
11:32:03
Добрый день, как возможно получить ID вставленных строк?
p = plpy.execute('INSERT INTO tables VALUES ....')

crux
20.07.2018
11:33:40
INSERT INTO tables VALUES ... RETURNING id

Radim
20.07.2018
11:35:41

Sasha
20.07.2018
12:55:24

Gennady
20.07.2018
13:26:34
Да, это выдаётся в EXPLAIN (ANALYZE, ?BUFFERS?).
Проверил уменьшение work_mem ниже определённого порога приводит к резкому появлению lossy Heap Blocks (помимо exact), а также к появлению Rows Removed by Index Recheck.
Причём, количество Heap Block начинает делиться поровну между exact и lossy.
Само время выполнения увеличивается примерно в 4 раза.
Как я понял, в режиме exact вообще не выполняется recheck.
Значение work_mem, ниже которого появляется lossy Heap Blocks, зависит от отбираемого в where объёма данных.
Другого изменения грубости битовой карты я не обнаружил.

Yaroslav
20.07.2018
13:27:56

Gennady
20.07.2018
13:29:26
Ожидал хоть чего-то, спасибо за наводку.

Yaroslav
20.07.2018
13:32:21

Google

Gennady
20.07.2018
13:33:15
безусловного recheck, но с возможностью ручного управления грубостью битовой карты.
Кстати, производительность запроса с OR в таком exact-режиме получилась в 2 раза выше, чем с union.

Yaroslav
20.07.2018
13:39:39

Gennady
20.07.2018
14:44:38
create table tst as (select hashint4(s) as i, hashint4(s+1) as j from generate_series (1, 268435456, 1) s);
create index tst_i on tst using btree(i);
create index tst_j on tst using btree(j);
select *
from tst
where i between 1 and 60000000
or
j between 1 and 60000000;
Как есть, work_mem=70MB:
https://explain.depesz.com/s/N0PI
Как есть, work_mem=69MB:
https://explain.depesz.com/s/3adh
Переписать в uinon all:
https://explain.depesz.com/s/bEHp
Переписать в uinon:
https://explain.depesz.com/s/Lju3

Robert
20.07.2018
14:46:03
Робяты, вопрос по существу. Вызываю postgres из Go. Собственно разницы какой язык нет. Если в Go не вызывать функцию явного старта транзакции, то считается, что транзакция открывается и коммитится после исполнения команды автоматически. Вопрос. А если делать это явно, то это будет 3 вызова СУБД с клиента или их и сейчас три. Просто интересно, может для неявных транзакций в PG есть какой то флаг при отправке команды, что уменьшает 3 вызова до 1го.

Yaroslav
20.07.2018
14:54:36

Ilia
20.07.2018
14:56:13
Каждый оператор -- отдельная транзакция, сама коммитится (есил ошибки нет естественно)
https://postgrespro.ru/docs/postgrespro/10/ecpg-sql-set-autocommit
Запрос (roundtrip на сервер) будет один при этом

Yaroslav
20.07.2018
14:58:39
Да, было вот что:
SELECT *, CASE WHEN chat_id=‘1111111’ THEN 1 ELSE 2 END AS pr
FROM users
WHERE chat_id = '111111' OR username = 'alex'
ORDER BY pr
LIMIT 1;


Robert
20.07.2018
16:03:36
Спасибо!
так и предполагал конечно,что раундтрипов меньше при автокоммите :(

Ilia
20.07.2018
16:05:01
Ну не обязательно

Robert
20.07.2018
16:05:11
Почему спрашиваю. Оптимистичную блокировку через обновления поля row_version делаю. Раньше передавал в условие было типа UPDATE persons SET name =$1, row_version = row_version + 1 WHERE ID = $2 AND row_version = $3 RETURNING row_version;
ну типа в этом случае, если запись не найдена - то значит кто то ее уже обновил. Но мне не совсем это нравится, вдруг запись была удалена.
поэтому решил обернуть все в транзакцию и если при RETURNING row_version больше на 2 и выше (в идеале должна быть выше на 1), значит запись была изменена в другой транзакции. И тогда текущую можно откатывать и предупреждать пользователя.

Google

Ilia
20.07.2018
16:11:10

Robert
20.07.2018
16:15:25
да, но если записи с целевым ID не будет (потому что в другой транзакции ее удалили), то я то буду думать, что просто версия записи изменилась поэтому реального UPDATE не произошло.

Ilia
20.07.2018
16:17:38
Ну а что ж тебе откатывать, если её не произошло?
Ты только сообщение дашь, что была ошибка, и заново всё начнёшь...

Robert
20.07.2018
16:26:55
откатывать, но быть уверенным что запись с заданным ID в таблице есть.

Yaroslav
20.07.2018
16:27:49

Misha
20.07.2018
16:31:06
скорей всего за 1 update не выйдет узнать, что строка могла быть удалена

Robert
20.07.2018
16:32:36
Вот меня это и печалит. А три раундтрипа, не знаю какой даст оверхед. Надо будет эксперимент провести.

Misha
20.07.2018
16:33:57
может вам подойдет merge(upsert)?
какая должна быть логика в случае если данные были удалены в 1ой сессии, а во 2ой хотелось их апдейтить

Yaroslav
20.07.2018
16:35:16
А зачем вам что-то узнавать? В любом случае, если в ответ на UPDATE вы получаете, что обновлено ноль записей — это ошибка, и всё.

Robert
20.07.2018
16:37:27
Ярослав, там ведь в чем дело. Ага, запись обновлена в другой сессии. Тогда уведомляем пользователя и предлагаем варианты: 1) пофиг пляшем, записываем поверх нашу версию (и тогда в след улетевшем UPDATE пропадает условие на сверку row_version) или 2) считайка мне то что есть в БД. Гляну, что изменили.

Yaroslav
20.07.2018
16:41:11

Robert
20.07.2018
16:47:29
Прямо с козырей зашли :) да, согласен 1 вариант редкий. Помню использовали, на пред проектах, но в каких кейсах - вопрос.

Yaroslav
20.07.2018
16:50:25

Admin
ERROR: S client not available

Yaroslav
20.07.2018
17:01:47

Misha
20.07.2018
17:04:42
версия обычно берется из записи, которую селектили до этого, дальше идет апдейт любого поля(зачем все?) & version += 1 where version = oldversion

Robert
20.07.2018
17:05:33
Where version=$3 это как раз, то что получили раннее при select

Yaroslav
20.07.2018
17:05:48

Misha
20.07.2018
17:06:00
0 или 1

Google

Misha
20.07.2018
17:06:16
не нужен никакой сиквенс
пользователь всегда открывает перед редактированием?) иначе это кто-то шалит в бд напрямую
Нет, минуточку. :) Что такое "обычно"?
А инициализируется row version при создании записи как?

Robert
20.07.2018
17:08:17
В форме


Yaroslav
20.07.2018
17:17:14
0 или 1
Так это работает только для PK, основанного на sequence...
Смотрите:
INSERT INTO users(id, name, birth_date, version) VALUES (1, 'Вася', '2012-01-23', 1);
Далее, первая часть OCC, клиент 1 (выбирает запись и "уходит"):
SELECT * FROM users WHERE id = 1; — запоминаем: Id = 1 и rowversion = 1
Тем временем, другая транзакция:
BEGIN;
DELETE FROM users WHERE id = 1; — ошиблись, это был не Вася
INSERT INTO users(id, name, birth_date, version) VALUES (1, 'Петя', '2008-01-23', 1);
COMMIT;
Возвращается клиент 1, чтобы обновить Васину дату рождения (использует сохранённые значения):
UPDATE users SET birth_date = '2000-08-08' WHERE id = 1 AND rowversion = 1;
— UPDATE 1
Всё успешно, изменили дату рождения... только вот не того человека.
Если пример кажется надуманным, представьте, что это строки заказа, и кто-то считывает и хочет поменять первую, а тем временем кто-то другой её удаляет и вставляет совсем другую...


Misha
20.07.2018
17:22:17
зачем будут удалять запись с васей, а не просто update?
почему есть явная привязка к id? если будут инсертить вновь, то sequence.nextval и будет ошибка в первой сессии т.к. rows_updated = 0? Предположим, что там не id, а уникальный номер заказа, то тогда возвращаемся к первому вопросу)


Yaroslav
20.07.2018
17:26:44
зачем будут удалять запись с васей, а не просто update?
почему есть явная привязка к id? если будут инсертить вновь, то sequence.nextval и будет ошибка в первой сессии т.к. rows_updated = 0? Предположим, что там не id, а уникальный номер заказа, то тогда возвращаемся к первому вопросу)
> зачем будут удалять запись с васей
Потому что мне так захотелось. Я что, не имею права менять данные удобным мне способом? ;)
> почему есть явная привязка к id?
Ну, это какой-нибудь табельный номер в каком-то бумажном документе, например.
> если будут инсертить вновь, то sequence.nextval и будет ошибка в первой сессии т.к. rows_updated = 0?
Так вы же писали, что инициализируется 0 или 1?
> Предположим, что там не id, а уникальный номер заказа, то тогда возвращаемся к первому вопросу)
Строки заказа. Т.е. 1, 2, 3...


Misha
20.07.2018
17:33:07
> Так вы же писали, что инициализируется 0 или 1?
я к тому, что той записи уже не будет, т.к её удалили и ей присвоился новый ид => rows_updated = 0 => error(запись изменена)
> Потому что мне так захотелось. Я что, не имею права менять данные удобным мне способом? ;)
при желании можно ещё и чексумму вычислять, если уж так хочется. Тогда не будет апдейта Васи вместо Пети. Если хочется что-то сломать, то это всегда можно сделать)


Yaroslav
20.07.2018
17:39:43
> Так вы же писали, что инициализируется 0 или 1?
я к тому, что той записи уже не будет, т.к её удалили и ей присвоился новый ид => rows_updated = 0 => error(запись изменена)
> Потому что мне так захотелось. Я что, не имею права менять данные удобным мне способом? ;)
при желании можно ещё и чексумму вычислять, если уж так хочется. Тогда не будет апдейта Васи вместо Пети. Если хочется что-то сломать, то это всегда можно сделать)
> я к тому, что той записи уже не будет
Да, но это работает только в том случае, если ключ таблицы использует sequence. А если нет — не работает. Это всё, что я хотел сказать. :)
> при желании можно ещё и чексумму вычислять, если уж так хочется. Тогда не будет апдейта Васи вместо Пети.
С некоторой вероятностью. ;)
> Если хочется что-то сломать, то это всегда можно сделать)
Я что-то не вижу, каким образом можно сломать схему с sequence (или ключом на основании sequence).
Как это сделать?


Misha
20.07.2018
17:46:49
> Я что-то не вижу, каким образом можно сломать схему с sequence (или ключом на основании sequence).
Как это сделать?
А какая была ваша схема? использовать sequence для генерации чисел в row_version?
Я предпочел бы использовать время последнего апдейта, чем вам не естественный sequence

Radim
20.07.2018
17:57:28
Есть ли что-то поинтереснее с примерами по Plpython, нежели офф. документация?

Yaroslav
20.07.2018
17:59:24

Artem
20.07.2018
19:03:06
Юнит тестирование скриптов баз данных
https://habr.com/post/417569/
https://tsqlt.org/

Radim
21.07.2018
18:09:38
Гарантирует ли постгрес то, что при вставке множества значений
Insert into table (...) values
(...), (...)... returning "Id";
Он вернет id вставленных в том порядке, в котором они перечислены?

Darafei
21.07.2018
18:11:15
порядок без order by никто не гарантирует

Vladislav
21.07.2018
19:32:16
@Komzpa речь же про инсерт. какой там order by?

Darafei
21.07.2018
19:32:53
оборачиваешь в cte, делаешь из него select и там order by