И боюсь показаться некомпетентным, но зачем ключевое слово TABLE?
Это "синтаксический сахар", который позволяет писать короче обращение к CTE (или таблицам) вида 1 строка/1 столбец - в отдельной статье чуть больше информации.
возможно имея весь запрос было бы более понятно
Вряд ли. Алгоритмически - там по определенным правилам из нескольких таблиц собирается "большая" CTE, из которой потом по относительно небольшому набору ключей надо "выдернуть" некоторые записи.
Классический JOIN пары CTE дает Nested Loop с множественными проходами по "большой" CTE, из которой N-1 запись каждый раз бессмысленно отфильтровывается - об этом как раз и написано в статье про "ословаривание".
зачем реляционную CEБД PostgreSQL использовать таким образом - хранить сырые объекты в JSON?
Возможно, я недостаточно акцентировал внимание на том моменте, что этот кейс не про хранение JSON, а про его использование в качестве промежуточной структуры - либо как словаря с доступом по ключу вместо множественных CTE Scan, либо как параметра-выборки, передаваемого на вход запроса в качестве $1-значения.
Он почему-то неявно предполагает, что необходимый из достигнутых всеми путями узлов почему-то окажется первым при переборе. То есть сортировка по сумме длин путей не применена - а без ее учета мы рискуем получить 1 вместо 2.
хм...res &&= cachedVal превратится в 0 при первом же попадании cachedVal === 0, а дальше правая часть просто перестанет выполняться при следующих итерациях
Он здесь не прогоняется целиком и не итерируется, мы просто эмулируем миллион случайных обращений.
А кейс очень простой - при старте приложения вы можете поднимать некий заранее предрассчитанный кэш, который покрывает 99.9% обращений, а потом только обращаться к нему, не пытаясь его изменить. Вполне очевидно, что попытка добавления этих 0.1% разнообразных значений может со временем непотребно раздуть его.
В статье, указанной в последнем абзаце, как раз рассказывается, как конкретно работает Map "внутри" V8. Если коротко - причина в особенностях используемого в V8 алгоритма хэширования.
Если клиенту пришло 1000 записей, хотя по дизайну надо всего 25 для отрисовки - то зачем мы грузили БД начиткой лишних, если в 90% случаев пользователь все равно не прокрутит дальше первого экрана?
Да и ограничение на время работы выборки тоже можно применить в последовательном переборе.
Как правило, при таком "обычном" переборе и так не возникает проблем со временем исполнения запроса - они достаточно быстры. Просто их приходится делать очень много, чтобы нарисовать хоть что-то.
Приведенный способ как раз и позволяет сократить их количество, заодно сократив непроизводительные затраты каждой итерации.
Для подобного выражения одна из типовых задач - префиксный поиск по btree-индексу или триграммный по подстроке или FTS-поиск по gin/gist.
Вот это - про TABLE?
Это "синтаксический сахар", который позволяет писать короче обращение к CTE (или таблицам) вида 1 строка/1 столбец - в отдельной статье чуть больше информации.
Вряд ли. Алгоритмически - там по определенным правилам из нескольких таблиц собирается "большая" CTE, из которой потом по относительно небольшому набору ключей надо "выдернуть" некоторые записи.
Классический JOIN пары CTE дает Nested Loop с множественными проходами по "большой" CTE, из которой N-1 запись каждый раз бессмысленно отфильтровывается - об этом как раз и написано в статье про "ословаривание".
Возможно, я недостаточно акцентировал внимание на том моменте, что этот кейс не про хранение JSON, а про его использование в качестве промежуточной структуры - либо как словаря с доступом по ключу вместо множественных
CTE Scan, либо как параметра-выборки, передаваемого на вход запроса в качестве$1-значения.Не-не, что вы! ))
jsdтут - это CTE, которую собрали сначала из нормальных реляционных записей в базе.Согласен, nodes[0] проглядел. Первый встреченный узел с "полным" счетчиком будет искомым.
Однако, в приведенном python-коде видится ошибка:
Он почему-то неявно предполагает, что необходимый из достигнутых всеми путями узлов почему-то окажется первым при переборе. То есть сортировка по сумме длин путей не применена - а без ее учета мы рискуем получить 1 вместо 2.
Впрочем, необходимые правки тривиальны.
Запись видима транзакции, но добавил "для" во избежание разночтений.
Правильнее "ты не должен этого хотеть". Но последнее время - именно та. ))
Однако, в нашем тесте до 64K ключей Map показал себя лучше и при отсутствии вставок/удалений.
На миллионном кэше у меня Map : Object получилось 550ms : 400ms = 1.375, тут 454ms : 377ms = 1.20, примерно так же.
хм...
res &&= cachedValпревратится в 0 при первом же попаданииcachedVal === 0, а дальше правая часть просто перестанет выполняться при следующих итерацияхОн здесь не прогоняется целиком и не итерируется, мы просто эмулируем миллион случайных обращений.
А кейс очень простой - при старте приложения вы можете поднимать некий заранее предрассчитанный кэш, который покрывает 99.9% обращений, а потом только обращаться к нему, не пытаясь его изменить. Вполне очевидно, что попытка добавления этих 0.1% разнообразных значений может со временем непотребно раздуть его.
В статье, указанной в последнем абзаце, как раз рассказывается, как конкретно работает Map "внутри" V8. Если коротко - причина в особенностях используемого в V8 алгоритма хэширования.
Скорректировал подпись - так более очевидно?
... оформлен не по ГОСТ 2.319-81... ))
А если еще вспомнить, что
'.'в regexp совсем не то же самое, что в качестве подстроки...Все правильно, и это все тоже можно обработать так же, но усложнения статьи это не стоило.
Да, но та же проблема с повторной заменой.
Так
UPDATEи обрабатывает запись (переписывает кортеж и накладывает блокировку) ровно в порядке чтения со страницы данных, если явно не указано иное.Если клиенту пришло 1000 записей, хотя по дизайну надо всего 25 для отрисовки - то зачем мы грузили БД начиткой лишних, если в 90% случаев пользователь все равно не прокрутит дальше первого экрана?
Как правило, при таком "обычном" переборе и так не возникает проблем со временем исполнения запроса - они достаточно быстры. Просто их приходится делать очень много, чтобы нарисовать хоть что-то.
Приведенный способ как раз и позволяет сократить их количество, заодно сократив непроизводительные затраты каждой итерации.