172 похожих чатов

Вопрос вроде популярный, но не смог найти ошибку в решении.

Нужно вытащить последнюю реинкарнацию организации - с максимальной org_version для данной org_id Почему postgres настолько ошибается в оценках и как сделать чтоб не ошибался?
rdb=# \d tt
Table "public.tt"
Column | Type | Collation | Nullable | Default
-------------+---------+-----------+----------+---------
org_id | integer | | |
org_version | integer | | |
Indexes:
"tt_id_version" btree (org_id, org_version)

rdb=#
rdb=# explain (buffers,analyze)
select * from tt d1,
(select org.org_id,
max(org.org_version) AS max_org_version
FROM tt org
WHERE org.org_id >= 0 GROUP by org.org_id) d2
where d1.org_id = d2.org_id and d1.org_version = d2.max_org_version;
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------
Hash Join (cost=56.28..80.23 rows=6 width=16) (actual time=0.609..0.869 rows=847 loops=1)
Hash Cond: ((d1.org_id = org.org_id) AND (d1.org_version = (max(org.org_version))))
Buffers: shared hit=12
-> Seq Scan on tt d1 (cost=0.00..17.77 rows=1177 width=8) (actual time=0.012..0.074 rows=1177 loops=1)
Buffers: shared hit=6
-> Hash (cost=43.56..43.56 rows=848 width=8) (actual time=0.587..0.588 rows=847 loops=1)
Buckets: 1024 Batches: 1 Memory Usage: 42kB
Buffers: shared hit=6
-> HashAggregate (cost=26.60..35.08 rows=848 width=8) (actual time=0.391..0.485 rows=847 loops=1)
Group Key: org.org_id
Batches: 1 Memory Usage: 169kB
Buffers: shared hit=6
-> Seq Scan on tt org (cost=0.00..20.71 rows=1177 width=8) (actual time=0.007..0.128 rows=1176 loops=1)
Filter: (org_id >= 0)
Rows Removed by Filter: 1
Buffers: shared hit=6
Planning:
Buffers: shared hit=3
Planning Time: 0.352 ms
Execution Time: 0.959 ms
(20 rows)

rdb=#

17 ответов

12 просмотров

И Вы нашли для этого один из наихудших способов. ;( Почему бы не попробовать что-то получше (LATERAL, если есть таблица организаций; loose index scan (rCTE) или DISTINCT ON, если нет)? И, кстати, что б ему и не ошибаться в этом случае (в таблице даже ни одного ключа нет)? ;)

Sergey-Gr Автор вопроса
Yaroslav Schekin
И Вы нашли для этого один из наихудших способов. ;...

Я вот эти все извращения не очень понимаю. Но даже если сделать уникальный индекс на оба поля - всё равно ошибается. Надо объявить его как Primary Key?

Sergey Gr
Я вот эти все извращения не очень понимаю. Но даже...

Не понимаете — сидите с [в среднем так бывает] производительностью на два порядка (или более) худшей, чем могла бы быть — дело Ваше. ;( > всё равно ошибается. А ANALYZE выполняли? И вообще, это план на реальных данных (иначе обсуждать это я практического смысла не вижу)?

Sergey-Gr Автор вопроса
Yaroslav Schekin
Не понимаете — сидите с [в среднем так бывает] пр...

В реальности таблица шире, число строк точное. Analyze делал

Sergey Gr
В реальности таблица шире, число строк точное. Ana...

Тогда нужно копаться с конкретными данными и смотреть, как планировщик оценивает этот JOIN (но "чудо" там вряд ли будет — подобные оценки в принципе довольно грубы)...

Yaroslav Schekin
И Вы нашли для этого один из наихудших способов. ;...

А, собственно, почему? По-моему, как в его случае (когда org_version в среднем не сильно большэ одного на org_id) -- вменяемый довольно способ. Хотя, конечно... Планировщик за такое спасибо не скажэт.

Зачем для каждой организации свой счетчик, можно же сделать один на всех и брать его max + фильтр по org_id?

Ilya Anfimov
А, собственно, почему? По-моему, как в его случае...

Потому что объективные измерения (benchmarks) альтернативных способов (даже для разных распределений данных) показывают, что это так — погуглите или попробуйте.

Кстати, если чаще всего нужэн максимальный org_version -- то имеет смысл начинать с создания индэкса (org_id, org_version DESC) Чуть-чуть быстрее будут типичные операцыи и чуть-чуть лояльнее к нему отнесётся планировщик.

Yaroslav Schekin
Не понимаете — сидите с [в среднем так бывает] пр...

Да на какие два порядка, не будет там 10мкс на 1000 строк хоть обпишысь...

Yaroslav Schekin
И Вы нашли для этого один из наихудших способов. ;...

Кстати, я правильно помню, что самый поддержываемый синтаксисом DISTINCT ON -- до сих пор не умеет index skip scan?

Yaroslav Schekin
И Вы нашли для этого один из наихудших способов. ;...

И, в итоге, самый быстрый результат таких запросов -- пишэтся через WITH RECURSIVE ? (Но и то -- не за счёт того, что планировщик там что-то понимает, а как раз наоборот).

Ilya Anfimov
Да на какие два порядка, не будет там 10мкс на 100...

Где я говорил именно про 1000 строк?! Я написал "в среднем так бывает", безотносительно к конкретному примеру (я вообще подумал, что это просто тестовые данные / демонстрация).

Ilya Anfimov
Кстати, я правильно помню, что самый поддержываемы...

Так такого executor node до сих пор не существует — как он может его "уметь"? ;(

Ilya Anfimov
И, в итоге, самый быстрый результат таких запросов...

Самый быстрый (в норме) — LATERAL (или DISTINCT ON, если на каждое значение... org_id, в этом случае, приходится только 2-3 rows).

Ну, мало ли... На WITH RECURSIVE разложыть, например... Да и вообще. Есть многое на свете, друг Горацый, что мне лично и не снилось.

Ilya Anfimov
Ну, мало ли... На WITH RECURSIVE разложыть, наприм...

Не, все ждут, пока https://wiki.postgresql.org/wiki/Loose_indexscan кто-то "честно" реализует, зачем нам полумеры? ;)

Похожие вопросы

Обсуждают сегодня

а зачем этот вопрос для удаления из чата?
Mёdkinson Medvezhkin
63
Добрый день. Хочу сделать отрисовку по команде на панели. Почему-то рисуется только при втором вызове. С чем может быть связано, не подскажете? procedure TForm1.FormDblClick(...
Kirill Filippenok
20
Всем доброго дня! Подскажите может кто использовал связку Pagebuilder + Clientsetting. Сами параметры с типом pagebuilder в модуле Clientsetting работают нормально, можно такж...
Александр Добриков
12
А почему в си некоторые вещи работают с двойными кавычками некоторые с одинарными? Нельзя было все сделать с одними или чтоб работало с разными? например чтоб выводить строки ...
.
15
Всем привет! Нужен совет от опытных. Переношу свой проект с Делфи 10.2 Токио на Лазарус 3.2 установленный через инсталлятор fpcupdeluxe-x86_64-win64. При импортировании проект...
Дмитрий Завгородний
7
Эх кто-то пришел и весь праздник испортил :( You need complex FBX scene importing setup to change things on import? good luck with that. You need navigation and pathfinding? g...
Serg Gini
5
Всем привет! Подскажите. Я написал приложение на Delphi 10.2 Tokyo под Windows 10. И передо мной стал вопрос о том чтобы сделать это приложение кроссплатформенным (под Linux и...
Дмитрий Завгородний
24
Всем привет! procedure TForm1.FormCreate(Sender: TObject); type TStartEnd = record S: Byte; E: Byte; end; var a, b: TStartEnd; begin {1} a.S := 1; {2} a.E := 2; ...
Руслан Михайлович
10
Всем привет!) я тут новенький и пытаюсь освоить evolution методом тыка. У меня при переходе между папками файлов выскакивают вот такие уведомления Можете подсказать как их от...
Диман Samoed
10
Какого хера? /Sources/App/Modules/User/Models/UserLinkApple.swift:21:20: warning: stored property '_id' of 'Sendable'-conforming class 'UserLinkApple' is mutable @ID(...
Alexander Sherbakov
14
Карта сайта