This media is not supported in your browser
VIEW IN TELEGRAM
Колонарное хранилище vs построчное (row store) наглядно
Берем простую агрегацию и сравниваем, как она выполняется в row store и columnar store.
В row store данные лежат строками, поэтому движку приходится читать каждую строку целиком, чтобы из нее вытащить значение колонки age.
В columnar store данные лежат по колонкам, поэтому он читает сразу только значения колонки age, без трогания остальных полей и без лишнего I/O.
👉 @BackendPortal
Берем простую агрегацию и сравниваем, как она выполняется в row store и columnar store.
В row store данные лежат строками, поэтому движку приходится читать каждую строку целиком, чтобы из нее вытащить значение колонки age.
В columnar store данные лежат по колонкам, поэтому он читает сразу только значения колонки age, без трогания остальных полей и без лишнего I/O.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤8👍2
This media is not supported in your browser
VIEW IN TELEGRAM
JavaScript, Ruby и Go используют сборщик мусора для управления памятью.
Но ты знал, что у SSD тоже есть свой GC?
SSD с большим количеством записей и удалений постоянно “перекладывает” данные, и этим занимается сборщик мусора, встроенный прямо в прошивку, которая крутится на контроллере SSD.
Из-за этого последовательная запись до сих пор предпочтительнее случайной, даже если у тебя не HDD.
👉 @BackendPortal
Но ты знал, что у SSD тоже есть свой GC?
SSD с большим количеством записей и удалений постоянно “перекладывает” данные, и этим занимается сборщик мусора, встроенный прямо в прошивку, которая крутится на контроллере SSD.
Из-за этого последовательная запись до сих пор предпочтительнее случайной, даже если у тебя не HDD.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤3
JSON и JSONB колонки удобны тем, что туда можно просто закинуть любые “безсхемные” данные, но иногда хочется хоть немного это зажать правилами.
Для этого можно использовать расширение
👉 @BackendPortal
Для этого можно использовать расширение
pg_jsonschema: задаешь JSON Schema и получаешь больше контроля над тем, какой формы данные вообще имеют в этих колонках.Please open Telegram to view this post
VIEW IN TELEGRAM
❤6
SYN Flood это одна из самых старых DoS-атак, и она до сих пор работает. Вот что происходит под капотом.
TCP-соединение поднимается через three-way handshake: клиент шлет SYN, сервер отвечает SYN-ACK, клиент завершает ACK.
Фишка в том, что на этом этапе сервер держит состояние для каждой “полуоткрытой” сессии в очереди backlog и под это выделяются ресурсы.
В SYN Flood атакующий шлет тысячи SYN-пакетов, но рукопожатие не завершает. Сервер продолжает ждать ACK, backlog забивается, и когда очередь переполнена, легитимные клиенты уже не могут подключиться. Получается DoS.
Почему атака такая живучая: из-за асимметрии. Нападающий кидает крошечные пакеты почти бесплатно, а серверу на каждый приходится тратить ресурсы. Даже слабая машина может уложить куда более мощный сервер.
Факт: SYN-флуды в прошлом валили GitHub, Cloudflare и разные базы. Защита обычно такая:
1. лимитить SYN от одного IP
2. дропать пакеты от известных плохих источников
3. и самое эффективное: SYN cookies
С SYN cookies сервер вообще ничего не хранит на этапе “полуоткрыто”. Он кодирует нужную инфу (IP клиента, порт, таймстамп и т.д.) в initial sequence number у SYN-ACK, который отправляет в ответ. Номер генерируется криптографически, подделать его сложно.
В итоге handshake становится по сути stateless со стороны сервера, пока клиент не докажет, что он реальный. Ресурсы резервируются только после верификации.
Кстати, в большинстве современных ОС поддержка SYN cookies уже встроена. В Linux это включается так:
Если хочется копнуть глубже, статьи в Wikipedia по теме реально норм, плюс можно добить деталями через любимую LLM.
👉 @BackendPortal
TCP-соединение поднимается через three-way handshake: клиент шлет SYN, сервер отвечает SYN-ACK, клиент завершает ACK.
Фишка в том, что на этом этапе сервер держит состояние для каждой “полуоткрытой” сессии в очереди backlog и под это выделяются ресурсы.
В SYN Flood атакующий шлет тысячи SYN-пакетов, но рукопожатие не завершает. Сервер продолжает ждать ACK, backlog забивается, и когда очередь переполнена, легитимные клиенты уже не могут подключиться. Получается DoS.
Почему атака такая живучая: из-за асимметрии. Нападающий кидает крошечные пакеты почти бесплатно, а серверу на каждый приходится тратить ресурсы. Даже слабая машина может уложить куда более мощный сервер.
Факт: SYN-флуды в прошлом валили GitHub, Cloudflare и разные базы. Защита обычно такая:
1. лимитить SYN от одного IP
2. дропать пакеты от известных плохих источников
3. и самое эффективное: SYN cookies
С SYN cookies сервер вообще ничего не хранит на этапе “полуоткрыто”. Он кодирует нужную инфу (IP клиента, порт, таймстамп и т.д.) в initial sequence number у SYN-ACK, который отправляет в ответ. Номер генерируется криптографически, подделать его сложно.
В итоге handshake становится по сути stateless со стороны сервера, пока клиент не докажет, что он реальный. Ресурсы резервируются только после верификации.
Кстати, в большинстве современных ОС поддержка SYN cookies уже встроена. В Linux это включается так:
net.ipv4.tcp_syncookies = 1.Если хочется копнуть глубже, статьи в Wikipedia по теме реально норм, плюс можно добить деталями через любимую LLM.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7
А что если можно копировать гигабайты данных, вообще не копируя их?
Базы, рантаймы языков и ОС по сути так и делают через copy-on-write (COW).
Классический пример: fork процесса.
Когда ты форкаешь unix-процесс, формально создается полная копия памяти родителя. Но реально дублировать гигабайты RAM было бы адски медленно и тупо расточительно.
Поэтому сначала оба процесса просто указывают на одни и те же страницы памяти. А настоящая копия страницы делается только в момент записи, когда кто-то пытается ее поменять. В итоге копирование откладывается, и ты вообще не платишь за те данные, которые не меняются.
Языки программирования типа PHP и Ruby используют похожую идею. Когда ты присваиваешь уже существующее значение новой переменной, копия не создается сразу, она появляется только если значение потом модифицируют.
👉 @BackendPortal
Базы, рантаймы языков и ОС по сути так и делают через copy-on-write (COW).
Классический пример: fork процесса.
Когда ты форкаешь unix-процесс, формально создается полная копия памяти родителя. Но реально дублировать гигабайты RAM было бы адски медленно и тупо расточительно.
Поэтому сначала оба процесса просто указывают на одни и те же страницы памяти. А настоящая копия страницы делается только в момент записи, когда кто-то пытается ее поменять. В итоге копирование откладывается, и ты вообще не платишь за те данные, которые не меняются.
Языки программирования типа PHP и Ruby используют похожую идею. Когда ты присваиваешь уже существующее значение новой переменной, копия не создается сразу, она появляется только если значение потом модифицируют.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤6🔥2
Каждый разработчик должен понимать: изоляция арендаторов это не проблема базы данных.
Это проблема масштаба последствий.
Я понял это на практике.
Один пропущенный фильтр по арендатору.
И обычный выклад превращается в инцидент безопасности.
Любая система с несколькими арендаторами рано или поздно выбирает один из трёх уровней изоляции.
У каждого свой баланс между безопасностью, ценой и операционной проблемой.
1. Отдельная база данных на арендатора
Самая сильная изоляция. У каждого арендатора своя база. Никаких общих таблиц. Никакого общего состояния.
Плюсы очевидны.
Баг в одном арендаторе не утечёт в данные другого. Проверки проще. Разговоры про соответствие требованиям короче. Если что-то ломается, масштаб последствий небольшой.
Минусы приходят позже.
Нагрузка на сопровождение растёт очень быстро. Сотни или тысячи баз. Миграции превращаются в оркестрацию. Стоимость растёт вместе с числом арендаторов, а не с реальным использованием.
Подходит, когда арендаторы крупные, сильно регулируемые или с высоким риском. Плохо работает, если бездумно применять к “длинному хвосту” мелких клиентов.
2. Отдельная схема на арендатора
Средний вариант, который многие недооценивают.
Одна база на всех, но у каждого арендатора отдельная схема. Таблицы изолированы, а инфраструктура остаётся более-менее управляемой.
Границы яснее, чем при изоляции по строкам. Нет взрыва количества баз. Проверки остаются разумными. Большинство случайных утечек просто исчезают.
Но сложность всё равно накапливается.
Миграции нужно прогонять по множеству схем. Отчёты по всем арендаторам сразу становятся неудобными. Автоматизация не опция, а необходимость. Без неё модель разваливается под собственным весом.
Хорошо подходит, когда арендаторы сильно отличаются по размеру и хочется изоляцию без полной физической раздельности.
3. Изоляция по строкам
Самый дешёвый и самый опасный вариант.
Все арендаторы сидят в одних таблицах. Изоляция держится на столбце
Риск жесткий.
Один пропущенный фильтр и утечка данных. Один рефакторинг и изоляция сломалась. Один спешный хотфикс и можно открыть доступ ко всему. Безопасность зависит от того, что каждый слой всегда всё делает правильно.
Это работает только если поставить мощные “перила”: жёсткое ограничение запросов по арендатору, политики на уровне базы, принудительная проверка на уровне сервисов, и тесты, которые специально пытаются выйти за границы арендатора.
Без этого ты ставишь компанию на дисциплину.
Изоляция арендаторов это не выбор способа хранения. Это решение про доверие.
Запомни: это классический вопрос на собеседованиях.
👉 @BackendPortal
Это проблема масштаба последствий.
Я понял это на практике.
Один пропущенный фильтр по арендатору.
И обычный выклад превращается в инцидент безопасности.
Любая система с несколькими арендаторами рано или поздно выбирает один из трёх уровней изоляции.
У каждого свой баланс между безопасностью, ценой и операционной проблемой.
1. Отдельная база данных на арендатора
Самая сильная изоляция. У каждого арендатора своя база. Никаких общих таблиц. Никакого общего состояния.
Плюсы очевидны.
Баг в одном арендаторе не утечёт в данные другого. Проверки проще. Разговоры про соответствие требованиям короче. Если что-то ломается, масштаб последствий небольшой.
Минусы приходят позже.
Нагрузка на сопровождение растёт очень быстро. Сотни или тысячи баз. Миграции превращаются в оркестрацию. Стоимость растёт вместе с числом арендаторов, а не с реальным использованием.
Подходит, когда арендаторы крупные, сильно регулируемые или с высоким риском. Плохо работает, если бездумно применять к “длинному хвосту” мелких клиентов.
2. Отдельная схема на арендатора
Средний вариант, который многие недооценивают.
Одна база на всех, но у каждого арендатора отдельная схема. Таблицы изолированы, а инфраструктура остаётся более-менее управляемой.
Границы яснее, чем при изоляции по строкам. Нет взрыва количества баз. Проверки остаются разумными. Большинство случайных утечек просто исчезают.
Но сложность всё равно накапливается.
Миграции нужно прогонять по множеству схем. Отчёты по всем арендаторам сразу становятся неудобными. Автоматизация не опция, а необходимость. Без неё модель разваливается под собственным весом.
Хорошо подходит, когда арендаторы сильно отличаются по размеру и хочется изоляцию без полной физической раздельности.
3. Изоляция по строкам
Самый дешёвый и самый опасный вариант.
Все арендаторы сидят в одних таблицах. Изоляция держится на столбце
tenant_id и на том, как ты пишешь запросы. Инфраструктура простая, цена низкая, масштабировать легко.Риск жесткий.
Один пропущенный фильтр и утечка данных. Один рефакторинг и изоляция сломалась. Один спешный хотфикс и можно открыть доступ ко всему. Безопасность зависит от того, что каждый слой всегда всё делает правильно.
Это работает только если поставить мощные “перила”: жёсткое ограничение запросов по арендатору, политики на уровне базы, принудительная проверка на уровне сервисов, и тесты, которые специально пытаются выйти за границы арендатора.
Без этого ты ставишь компанию на дисциплину.
Изоляция арендаторов это не выбор способа хранения. Это решение про доверие.
Запомни: это классический вопрос на собеседованиях.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤6👍2
Датабейз штуки, которые я бы изучал, если бы хотел реально глубоко понять масштабирование:
Сохрани в закладки.
▪️ B+ деревья
▪️ LSM-деревья
▪️ Write-Ahead Logging (WAL)
▪️ Двухфазный коммит (2PC)
▪️ Трехфазный коммит (3PC)
▪️ Реплики для чтения (read replicas)
▪️ Репликация leader-follower
▪️ Партиционирование (partitioning)
▪️ Кэширование запросов (query caching)
▪️ Вторичные индексы (secondary indexes)
▪️ Векторные индексы (FAISS, HNSW)
▪️ Распределенные join’ы (distributed joins)
▪️ Материализованные представления (materialized views)
▪️ Event Sourcing
▪️ Change Data Capture (CDC)
👉 @BackendPortal
Сохрани в закладки.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
Не пиши в SQL = NULL или != NULL
Для NULL всегда используй IS NULL / IS NOT NULL
NULL это “нет значения / неизвестно”, и обычные операторы сравнения (=, !=, <, >) с ним не работают, потому что NULL не равен, не больше и не меньше вообще ничего.
= / != сравнивают значения. А NULL это не значение, а отсутствие значения. Поэтому IS / IS NOT проверяют именно наличие или отсутствие значения.
👉 @BackendPortal
Для NULL всегда используй IS NULL / IS NOT NULL
NULL это “нет значения / неизвестно”, и обычные операторы сравнения (=, !=, <, >) с ним не работают, потому что NULL не равен, не больше и не меньше вообще ничего.
= / != сравнивают значения. А NULL это не значение, а отсутствие значения. Поэтому IS / IS NOT проверяют именно наличие или отсутствие значения.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤11
This media is not supported in your browser
VIEW IN TELEGRAM
Топовый лайфхак с GitHub: добавь 0 к URL pull request, и ИИ поможет тебе ревьюнуть и понять изменения, которые хотят влить.
👉 @BackendPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
❤5😁2
Cursor недавно выкатил Composer, свою agentic-модель для кодинга, и заявил, что агент может быть примерно в 4 раза быстрее. Alex Xu пообщался с командой Cursor, в частности с Lee Robinson, чтобы разобраться, как это устроено внутри и за счет чего получается скорость.
Кодовый агент это система, которая умеет взять задачу, изучить репозиторий, править сразу несколько файлов и итеративно доводить до состояния, где сборка и тесты проходят.
Внутри Cursor сначала работает роутер: он выбирает подходящую модель для запроса (в том числе Composer), чтобы дальше она вела задачу.
Дальше запускается цикл: вытягиваем самый релевантный код (retrieval контекста), через инструменты открываем и редактируем файлы, гоняем команды в песочнице. Как только тесты зеленые, задача закрыта.
Чтобы этот цикл не тормозил, Cursor опирается на три техники:
1. Mixture-of-Experts (MoE): разреженная MoE-архитектура, где на каждый токен активируется только часть весов модели.
2. Спекулятивный декодинг: маленькая модель черновиком накидывает сразу несколько токенов, а большая модель параллельно их проверяет, чтобы снизить задержку.
3. Уплотнение контекста (context compaction): старые шаги суммаризируются, а в промпте остается только активный рабочий набор, чтобы контекст по мере итераций не раздувался и оставался максимально релевантным и коротким.
Фулл статья
👉 @BackendPortal
Кодовый агент это система, которая умеет взять задачу, изучить репозиторий, править сразу несколько файлов и итеративно доводить до состояния, где сборка и тесты проходят.
Внутри Cursor сначала работает роутер: он выбирает подходящую модель для запроса (в том числе Composer), чтобы дальше она вела задачу.
Дальше запускается цикл: вытягиваем самый релевантный код (retrieval контекста), через инструменты открываем и редактируем файлы, гоняем команды в песочнице. Как только тесты зеленые, задача закрыта.
Чтобы этот цикл не тормозил, Cursor опирается на три техники:
1. Mixture-of-Experts (MoE): разреженная MoE-архитектура, где на каждый токен активируется только часть весов модели.
2. Спекулятивный декодинг: маленькая модель черновиком накидывает сразу несколько токенов, а большая модель параллельно их проверяет, чтобы снизить задержку.
3. Уплотнение контекста (context compaction): старые шаги суммаризируются, а в промпте остается только активный рабочий набор, чтобы контекст по мере итераций не раздувался и оставался максимально релевантным и коротким.
Фулл статья
Please open Telegram to view this post
VIEW IN TELEGRAM
Бесплатный инструмент для визуализации плана SQL : https://explain.datadoghq.com/
В настоящее время для PostgreSQL, MySQL, MSSQL и MongoDB
👉 @BackendPortal
В настоящее время для PostgreSQL, MySQL, MSSQL и MongoDB
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3🔥2
GitHub хранит миллионы репозиториев примерно так же, как они лежат у нас локально: буквально как git-репозитории. Ничего особо сверхъестественного
Только вместо одной копии GitHub хранит минимум три копии каждого репозитория, чтобы код никогда не потерялся. Эта система репликации у них называется Spokes.
Когда мы пушим код, запись не принимается, пока строгая “большинство” реплик не сможет применить изменение и получить тот же результат, то есть минимум 2 из 3.
Интересно, что система следит за реальным прикладным трафиком, чтобы детектить сбои. Если три запроса подряд падают на одном из серверов репозитория, сервер помечается оффлайн, и трафик уходит на другие реплики за секунды. Никаких heartbeat-ов, просто мониторинг реальных операций пользователей.
Каждая реплика живёт в отдельной стойке. Если падает целая стойка, репозитории остаются доступными, потому что другие копии лежат в других местах. А когда нужно чиниться после падения сервера, помогает весь кластер: чем больше кластер, тем быстрее он восстанавливается.
Spokes отказывает в write-операциях, если не может закоммитить их хотя бы в двух местах. Это гарантирует, что если твой push прошёл, код уже в безопасности.
И поэтому же GitHub отклоняет пуши при частичных авариях. Чтение ещё может работать, а запись падает, потому что система не готова рисковать потерей данных.
Примерно так GitHub хранит репозитории и, что важнее, выбирает простой дизайн с упором на консистентность, а не на “лишь бы запись прошла” при просадках по доступности/надёжности.
Надеюсь, тебе тоже было интересно.
👉 @BackendPortal
Только вместо одной копии GitHub хранит минимум три копии каждого репозитория, чтобы код никогда не потерялся. Эта система репликации у них называется Spokes.
Когда мы пушим код, запись не принимается, пока строгая “большинство” реплик не сможет применить изменение и получить тот же результат, то есть минимум 2 из 3.
Интересно, что система следит за реальным прикладным трафиком, чтобы детектить сбои. Если три запроса подряд падают на одном из серверов репозитория, сервер помечается оффлайн, и трафик уходит на другие реплики за секунды. Никаких heartbeat-ов, просто мониторинг реальных операций пользователей.
Каждая реплика живёт в отдельной стойке. Если падает целая стойка, репозитории остаются доступными, потому что другие копии лежат в других местах. А когда нужно чиниться после падения сервера, помогает весь кластер: чем больше кластер, тем быстрее он восстанавливается.
Spokes отказывает в write-операциях, если не может закоммитить их хотя бы в двух местах. Это гарантирует, что если твой push прошёл, код уже в безопасности.
И поэтому же GitHub отклоняет пуши при частичных авариях. Чтение ещё может работать, а запись падает, потому что система не готова рисковать потерей данных.
Примерно так GitHub хранит репозитории и, что важнее, выбирает простой дизайн с упором на консистентность, а не на “лишь бы запись прошла” при просадках по доступности/надёжности.
Надеюсь, тебе тоже было интересно.
Please open Telegram to view this post
VIEW IN TELEGRAM
The GitHub Blog
Building resilience in Spokes
Spokes is the replication system for the file servers where we store over 38 million Git repositories and over 36 million gists.It keeps at least three copies of every repository…
👍12
Твои Postgres-серваки сейчас плавятся? Поздравляю. И да, тебе нужен PG Dog.
Его основатель Lev один из самых сильных ребят в теме масштабирования и шардинга БД. Он делал это для Instacart, и его софт может сделать это и для тебя.
Если реплики начинают отставать, а IOPS упёрся в потолок, значит, пора.
https://pgdog.dev/
👉 @BackendPortal
Его основатель Lev один из самых сильных ребят в теме масштабирования и шардинга БД. Он делал это для Instacart, и его софт может сделать это и для тебя.
Если реплики начинают отставать, а IOPS упёрся в потолок, значит, пора.
https://pgdog.dev/
Please open Telegram to view this post
VIEW IN TELEGRAM
PgDog
Scale PostgreSQL horizontally
❤3👍2
Не пиши в SQL = NULL или != NULL
Для NULL всегда используй IS NULL / IS NOT NULL
NULL это “нет значения / неизвестно”, и обычные операторы сравнения (=, !=, <, >) с ним не работают, потому что NULL не равен, не больше и не меньше вообще ничего.
= / != сравнивают значения. А NULL это не значение, а отсутствие значения. Поэтому IS / IS NOT проверяют именно наличие или отсутствие значения.
👉 @BackendPortal
Для NULL всегда используй IS NULL / IS NOT NULL
NULL это “нет значения / неизвестно”, и обычные операторы сравнения (=, !=, <, >) с ним не работают, потому что NULL не равен, не больше и не меньше вообще ничего.
= / != сравнивают значения. А NULL это не значение, а отсутствие значения. Поэтому IS / IS NOT проверяют именно наличие или отсутствие значения.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤7
В этом туториале объясняется, что такое JWT, как они работают, какие бывают техники подписи и какие есть best practices по безопасности.
👉 @BackendPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
❤4
Dockerfile доктор уже тут: переписывает файлы Dockerfile для уменьшения размера и повышения безопасности
👉 @BackendPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
❤11🔥2
Строки в PostgreSQL неизменяемые и хранятся в heap. У каждой строки есть скрытый идентификатор CTID, который указывает на ее физическое местоположение на диске.
CTID это идентификатор-кортеж из двух частей: номер страницы и индекс (позиция) внутри этой страницы. Посмотреть его можно простым запросом:
Вывод будет выглядеть примерно так:
Что в CTID интересного: когда ты создаешь индекс по первичному ключу, индекс не хранит всю строку целиком. Он хранит значение ключа и CTID, который указывает на реальное место строки в heap.
Из-за этого выборки быстрые. Индекс дает CTID, и PostgreSQL прыгает напрямую в нужную физическую точку в heap, чтобы достать строку.
Но есть нюанс: CTID меняется при обновлении строки. PostgreSQL использует MVCC (Multi-Version Concurrency Control), поэтому update создает новую версию строки в другом физическом месте. Старый CTID становится невалидным, а у строки появляется новый.
Из-за этого индексы нужно обновлять при каждом обновлении строки. Значение ключа может остаться тем же, но CTID, на который оно указывает, меняется.
Интересные архитектурные решения. PostgreSQL сэкономил одно лишнее разыменование, сохраняя CTID, но теперь индекс нужно переписывать даже если меняются неиндексируемые колонки.
Вот почему я обожаю копаться во внутренностях СУБД :) Там сплошь интересные решения и компромиссы.
👉 @BackendPortal
CTID это идентификатор-кортеж из двух частей: номер страницы и индекс (позиция) внутри этой страницы. Посмотреть его можно простым запросом:
SELECT ctid, * FROM your_table;
Вывод будет выглядеть примерно так:
(0,1), (0,2), (1,1), где первое число это страница, а второе это позиция.Что в CTID интересного: когда ты создаешь индекс по первичному ключу, индекс не хранит всю строку целиком. Он хранит значение ключа и CTID, который указывает на реальное место строки в heap.
Из-за этого выборки быстрые. Индекс дает CTID, и PostgreSQL прыгает напрямую в нужную физическую точку в heap, чтобы достать строку.
Но есть нюанс: CTID меняется при обновлении строки. PostgreSQL использует MVCC (Multi-Version Concurrency Control), поэтому update создает новую версию строки в другом физическом месте. Старый CTID становится невалидным, а у строки появляется новый.
Из-за этого индексы нужно обновлять при каждом обновлении строки. Значение ключа может остаться тем же, но CTID, на который оно указывает, меняется.
Интересные архитектурные решения. PostgreSQL сэкономил одно лишнее разыменование, сохраняя CTID, но теперь индекс нужно переписывать даже если меняются неиндексируемые колонки.
Вот почему я обожаю копаться во внутренностях СУБД :) Там сплошь интересные решения и компромиссы.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4🔥4❤1