
Terminator
30.08.2018
07:34:39
@misterjulian будет жить. Поприветствуем!

MikaelBox
30.08.2018
07:59:24
А скобку можно закрыть и в новой строке

valera
30.08.2018
08:05:08
Спасибо разобрадся

Google

Mike Chuguniy
30.08.2018
09:12:21

Eagle Owl
30.08.2018
09:15:35

Terminator
30.08.2018
09:48:08
Алтынбек Шарипов будет жить. Поприветствуем!
@pensnarik будет жить. Поприветствуем!


Andrey
30.08.2018
10:28:29
Помогите понять планировщик. Есть таблица, индекс по created_at (DESC) (timestamptz). Строки отсекаются по дате. Если в запросе присутствует фильтр по полю STATUS (по нему есть индекс, но он не используется), то запрос выполняется медленно (90% строк имеют статус 'domestic_delivered'). Если условия по STATUS нет, то быстро. Причём если условие на неравенство, то запрос также работает быстро.
План медленного запроса: https://explain.depesz.com/s/uAK
План быстрого запроса: https://explain.depesz.com/s/N9YO
Медленный запрос:
explain (analyze, verbose, buffers)
SELECT packages.created_at
FROM "packages"
WHERE (packages.status = 'domestic_delivered') AND
(packages.created_at >= '2018-08-29 17:00:00+00')
ORDER BY packages.created_at DESC LIMIT 50
Быстрый запрос:
explain (analyze, verbose, buffers)
SELECT packages.created_at
FROM "packages"
WHERE (packages.created_at >= '2018-08-29 17:00:00+00')
ORDER BY packages.created_at DESC LIMIT 50


Denis
30.08.2018
10:33:46
в быстром запросе происходит только обращение к индексу, и оно все читает из кэша (buffers hit), к диску даже не обращается. в то же время в медленном, чтобы проверить дополнительное условие, кроме индекса, базе нужно обращаться к таблице, а это уже медленнее и с промахом в кэше (buffers read).


Andrey
30.08.2018
10:41:08
Как тогда объяснить тот факт, что с условием на != запрос также работает быстро?
Ведь ему всё равно надо так же проверять все записи, которые он достал по индексу.
Limit (cost=0.57..585.61 rows=50 width=8) (actual time=0.017..0.316 rows=50 loops=1)
Output: created_at
Buffers: shared hit=132
-> Index Scan using package_created_at_desc_index on public.packages (cost=0.57..593110.08 rows=50690 width=8) (actual time=0.015..0.290 rows=50 loops=1)
Output: created_at
Index Cond: (packages.created_at >= '2018-08-29 17:00:00+00'::timestamp with time zone)
Filter: ((packages.status)::text <> 'domestic_delivered'::text)
Buffers: shared hit=132
Planning time: 0.234 ms
Execution time: 0.344 ms

Darafei
30.08.2018
10:42:17
там же index scan и index only scan воюют
в индекс надо поле status добавить, будет быстрее

Andrey
30.08.2018
10:44:30
Ох ты ж ёлки.
Хотя нет. При != тоже просто index scan, но работает быстро.

Google

Yaroslav
30.08.2018
10:47:46
Ох ты ж ёлки.
А зачем у Вас такой индекс "using package_created_at_desc_index", кстати?

Darafei
30.08.2018
10:48:44

Andrey
30.08.2018
10:49:35
Нету. Видимо, потому что 0?

Darafei
30.08.2018
10:50:45
Buffers: shared hit=49277 read=179172 dirtied=58358

Yaroslav
30.08.2018
10:51:31
Нету. Видимо, потому что 0?
Да. Поэтому производительность и отличается.
Сравните с: Rows Removed by Filter: 129574 у медленного запроса.

Andrey
30.08.2018
10:51:33

Darafei
30.08.2018
10:51:44
тут написано, что 58358 было испачкано

Sergey
30.08.2018
10:51:56

Darafei
30.08.2018
10:52:04
попробуйте ещё раз этот запрос выполнить

Denis
30.08.2018
10:52:11
просто при условии <> он быстро находит 50 записей себе и успокаивается

Yaroslav
30.08.2018
10:52:31

Darafei
30.08.2018
10:53:06
Но как?
может быть, никто никогда не читал эту таблицу и в ней хинты пришлось расставлять

Andrey
30.08.2018
10:53:08

Yaroslav
30.08.2018
10:53:52

Darafei
30.08.2018
10:53:59
а второй раз этот запрос столько же исполняется?

Yaroslav
30.08.2018
10:54:26

Andrey
30.08.2018
10:54:28

Google

Yaroslav
30.08.2018
10:58:08

Andrey
30.08.2018
10:59:45
Ну, хорошо. Не "должен", а "с большей вероятностью" )
Жаль, что нельзя trace включить как в Oracle.

Denis
30.08.2018
11:00:44
кстати, а у вас уменьшилось число строк в таблице по сравнению с предыдущими запросами? или ANALYZE выполнился?
там было rows=402913, а в последнем запросе в 8 раз меньше

Yaroslav
30.08.2018
11:03:59
Ну, хорошо. Не "должен", а "с большей вероятностью" )
Ну... как сказать. Вы (как и планировщик) считате, что в реальной жизни значения полей распределены равномерно и независимо.
Но почему это наиболее вероятно-то? ;)
Планировщик так считает, кстати, просто потому, что при отсутсвии дополнительной информации... попробуйте-ка придумать существенно лучшее предположение (а это самое простое). :(

Andrey
30.08.2018
11:04:18

Petr
30.08.2018
11:05:09
Здравствуйте!
15 сентября в московском офисе Авито пройдёт большой митап сообщества #RuPostgres.
Регистрируйтесь и приходите:
https://avitotech.timepad.ru/event/798808/?utm_refcode=fe260431fcd15def2d9306530800bee345d15775
Спасибо!

Denis
30.08.2018
11:05:38
Нет.
а, вы выше писали, что на status тоже есть индекс. видимо, из него статистика берется.

Богдан
30.08.2018
11:20:44
Господа, а не подскажите, можно ли результат оконной функции использовать в групировке GROUP BY?

Yaroslav
30.08.2018
11:20:46

Denis
30.08.2018
11:23:26
А как объясните, что планировщик пишет разное прогнозируемое чтсло строк? (Смотрели эксплейны по ссылкам?)

Yaroslav
30.08.2018
11:24:42

Denis
30.08.2018
11:26:55
А, ок. 1-й пункт не был для меня очевиден. Я думал, что статистика собирается только по индексируемым полям.

Yaroslav
30.08.2018
11:29:05

Богдан
30.08.2018
11:30:01
не подскажите, можно ли как-то без подзапроса сделать ?
select group_id, min(id) as id FROM
(select id, group_id, row_number() over (ORDER BY ID)- row_number() over (partition by group_id order by id) as gr
from users) as tb
group by group_id, gr
order by id
https://www.db-fiddle.com/f/byav3cdfcuc2vG2gDFnGwP/0

Yaroslav
30.08.2018
11:47:41

Богдан
30.08.2018
11:48:25

Yaroslav
30.08.2018
11:56:27

Богдан
30.08.2018
11:58:47

Google

valera
30.08.2018
12:04:18
Ребят, вопрос. Допустим, есть автоинкремент SERIAL, делается невалидный из-за NOT NULL инсерт, но автоинкремент все равно добавляет значение, и при следующем валидном инсерте первый кортеж уже идет с id 2. Как этого избежать?

Anton [Mgn, az09@osm]
30.08.2018
12:06:08

valera
30.08.2018
12:07:17
спасибо. какой для этого оператор? если ответ пару слов напишите плиз чтоб не искать в документации. первыф день прост БД учу

Yaroslav
30.08.2018
12:10:42
Ну Вы все правильно написали получить минимальное id, то это можно как-то сделать без подзапроса, или без вариантов?
А мне вот, например, кажется, что я неправильно написал. ;)
(Пример: insert into public.users(id, group_id) VALUES (1, 1), (2, 1), (3, 2), (3, 3), (4, 3), (6, 3), (7, 3); )
По тому, как я понял, я ожидал другого результата.
А пока непонятно, что запрос делает, подсказывать трудно. :(
Кстати, почему Вам важно, есть ли вложенный запрос или нет?

Anton [Mgn, az09@osm]
30.08.2018
12:10:44
Так это сложный философский вопрос кому доверить проверять валидность. Может клиент на фронте, может средний слой, но может и бд в конце концов

Yaroslav
30.08.2018
12:11:35


Богдан
30.08.2018
12:11:43
А мне вот, например, кажется, что я неправильно написал. ;)
(Пример: insert into public.users(id, group_id) VALUES (1, 1), (2, 1), (3, 2), (3, 3), (4, 3), (6, 3), (7, 3); )
По тому, как я понял, я ожидал другого результата.
А пока непонятно, что запрос делает, подсказывать трудно. :(
Кстати, почему Вам важно, есть ли вложенный запрос или нет?
вот все условие задачи:
дана таблица users вида - id, group_id
create temp table users(id bigserial, group_id bigint);
insert into users(group_id) values (1), (1), (1), (2), (1), (3);
1 В этой таблице, упорядоченной по ID необходимо:
2 выделить непрерывные группы по group_id с учетом указанного порядка записей (их 4)
3 подсчитать количество записей в каждой группе
4 вычислить минимальный ID записи в группе
Для таблицы:
id | group_id
----+----------
1 | 1
2 | 1
3 | 1
4 | 2
5 | 1
6 | 3
Непрерывными группами можно считать
group_id
----------
1
2
1
3

valera
30.08.2018
12:14:32
Все, понял, спасибо!

Denis
30.08.2018
12:15:37

valera
30.08.2018
12:16:21
я тоже так думаю, потому что если что то пойдет наперекосяк, то всю базу придется загружать заново

Yaroslav
30.08.2018
12:25:34
я тоже так думаю, потому что если что то пойдет наперекосяк, то всю базу придется загружать заново
Да не придётся...
Суть тут не в этом, а в том, что у поля, которое генерируется sequence (или identity), есть чёткий смысл — это генератор суррогатных ключей, и всё, что он гарантирует, это то, что они будут уникальными.

Богдан
30.08.2018
12:28:00

Yaroslav
30.08.2018
12:29:01

Anton [Mgn, az09@osm]
30.08.2018
12:56:48

Богдан
30.08.2018
13:02:17

Dima
30.08.2018
13:05:16
А какой стандартный пароль от юзера постгрес? Хочу подключатся в своей программе к бд.

Alex
30.08.2018
13:06:52

Dmitry
30.08.2018
13:07:02

Google

Terminator
30.08.2018
13:49:09
@archi_sova будет жить. Поприветствуем!

Айтуар
30.08.2018
15:30:40
Здравствуйте.
Скажите есть ли возможность задать пароль для postgres при initdb в переменной окружения или в параметре?
а всё нашёл в документации.

Alexey
30.08.2018
15:34:21

Айтуар
30.08.2018
15:34:41
--pwfile=имя_файла
Принуждает initdb читать пароль суперпользователя базы данных из файла, первая строка которого используется в качестве пароля.

Alexey
30.08.2018
15:34:54
-W
--pwprompt
Указывает initdb запросить пароль, который будет назначен суперпользователю базы данных. Это не важно, если не планируется использовать аутентификацию по паролю. В ином случае этот режим аутентификации оказывается неприменимым, пока пароль не задан.
ааа
ну можно было еще такой командой:
yes mypassword | initdb -W -D /path/to/db

Айтуар
30.08.2018
15:36:54
Это не наши методы (с)