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

Yaroslav @chAlx314 Как было замечено RhodiumToad из IRC:

I suspect something's stopping the planner from being able to
deduce that (t.o).id is safe to push through a GROUP BY ocd.o

that might be fixable by making it a separate column of its own

Поэтому было создано дополнительно поле order_id из (level0.o).id
SELECT * FROM (
SELECT
sum( level1.group_suma ) OVER( PARTITION BY level1.order_id ) AS total_suma,
*
FROM (
SELECT
sum( level0.item_suma ) AS group_suma,
level0.o,
(level0.o).id as order_id
FROM order_cost_details() level0
GROUP BY level0.o, (level0.o).id, (level0.ic).consumed_period
) level1
) level2
WHERE level2.order_id = 6154 -- works fast
WHERE (level2.o).id = 6154 -- works slow
Как было указано в [ответе на SO](https://stackoverflow.com/a/57004652/4632019)

новое поле решает проблему и планер может использовать значение 6154
для оптимизации.

Но проблема заключается в том, что этот трюк работает только для order_id
В других ситуация мне нужно фильтровать мой набор по agreement_id.
Я переписал запрос:
SELECT * FROM (
SELECT
sum( level1.group_suma ) OVER( PARTITION BY level1.order_id ) AS total_suma,
fn() as new_field
*,
FROM (
SELECT
sum( level0.item_suma ) AS group_suma,
level0.o,
(level0.o).id as order_id
(level0.o).agreement_id as agreement_id
FROM order_cost_details() level0
GROUP BY level0.o, (level0.o).id, (level0.ic).consumed_period
) level1
) level2
WHERE level2.agreement_id = 6154 -- works fast
Получается, что если я хочу, чтобы планер использовал значение в оптимизации,
то я должен выбирать необходимые поля явным образом, пока, со временем,
просто напрасто перечислю их всех.

Но зачем это делать, если я и так передаю все поля по ссылке:

level0.o в результате даёт одно поле, которое содержит остальные

Таким образом поле (level2.o).id и (level0.o).id - это одно и тоже значение в памяти,
грубо говоря - алиас.

Поэтому если я явно обращаюсь к level0, почему PG запрещает мне это делать?

Я совершенно не против ситуации, когда PG может запретить push для новых
полей, которые были созданы в этом уровне, как например:

(level0.o).agreement_id as order_id

Вот есть наши 3 запроса (см. картинку). level0 - исходные данные
и level1, level2 - полученные (derived) данные.
Соответсвенно мы не может делать какие либо манипуляции (например фильтровать)
на level0, если эти данные у нас появились только на level1

В моём примере, если я напишу level2.new_field = 3,
то планер может запросто переписать его на level1.new_field. Это безопасно.
планер не может переписать его на level0.new_field,
т.к. на level0 этого поля нет.

Аналогично: level2.order_id -> level1.order_id. Это безопасно.
планер может переписать его на (level0.o).id,
т.к. на level0 это поле есть и (level0.o).id удовлетворяет условию группировки. (GROUP BY)

Я бы предложил рассматривать эти примеры не как push, а как bubbling.

тогда наше поле id всплывает вот так: id -> order_id -> order_id

А теперь по поводу ссылок. Наше о всплывает так: o -> o -> o
На всех уровнях - это одно и тоже о. Значит если я говорю:

o.id = 6154 или какое либо другие поля по ссылке (я имею ввиду o)

То база данных должна сделать фильтрацию на level0, а потом уже получать данные из верхних уровней.
Я тут говорю должна, потому что я обращаюсь к o по ссылке,
а не как к полученному (derived) полю

2 ответов

16 просмотров

Я Вам уже писал — Вы пишете "простыни", которые очень трудно для чего-то использовать! ;( Т.е. используя то, что Вы написали, воспроизвести проблему никто, кроме Вас, не может. Давайте minimal test case, потому что иначе вряд ли это кому-то (влкючая -hackers) будет интересно, понимаете?

Подозреваю, что запор происходит в процессе группировки: она по .o, а .o.id - это уже не значение, а вычисляемое поле. Должно ли так быть и может ли так не быть в общем случае, не знаю. Но поддержу идею, что для разборок необходим компактный тестовый пример с данными. Рекомендую выложить его на dbfiddle.uk, чтобы сразу были видны результаты запросов и можно было поиграть с параметрами.

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

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

Господа, а что сейчас вообще с рынком труда на делфи происходит? Какова ситуация?
Rꙮman Yankꙮvsky
29
А вообще, что может смущать в самой Julia - бы сказал, что нет единого стандартного подхода по многим моментам, поэтому многое выглядит как "хаки" и произвол. Короче говоря, с...
Viktor G.
2
30500 за редактор? )
Владимир
47
а через ESC-код ?
Alexey Kulakov
29
Чёт не понял, я ж правильной функцией воспользовался чтобы вывести отладочную информацию? но что-то она не ловится
notme
18
У меня есть функция где происходит это: write_bit(buffer, 1); write_bit(buffer, 0); write_bit(buffer, 1); write_bit(buffer, 1); write_bit(buffer, 1); w...
~
14
Добрый день! Скажите пожалуйста, а какие программы вы бы рекомендовали написать для того, чтобы научиться управлять памятью? Можно написать динамический массив, можно связный ...
Филипп
7
Недавно Google Project Zero нашёл багу в SQLite с помощью LLM, о чём достаточно было шумно в определённых интернетах, которые сопровождались рассказами, что скоро всех "ибешни...
Alex Sherbakov
5
Ребят в СИ можно реализовать ООП?
Николай
33
https://github.com/erlang/otp/blob/OTP-27.1/lib/kernel/src/logger_h_common.erl#L174 https://github.com/erlang/otp/blob/OTP-27.1/lib/kernel/src/logger_olp.erl#L76 15 лет назад...
Maksim Lapshin
20
Карта сайта