🤡 Иллюзия оптимизации: индекс на is_active только вредит
Кажется логичным: если в запросах часто есть
⚙️ Почему база его не использует
Индексу важно разнообразие значений (кардинальность). Представь предметный указатель в конце книги: если слово встречается на 90% страниц, проще пролистать всю книгу целиком.
Оптимизатор рассуждает так же. Если значений всего два (true/false), он выберет полное сканирование таблицы (Seq Scan). Читать данные подряд намного быстрее, чем постоянно прыгать туда-сюда между индексом и таблицей.
📉 В чем реальный вред
Проигнорированный индекс становится мертвым грузом:
🔹 При каждом
🔹 Индекс впустую съедает место на диске и вытесняет из оперативной памяти действительно полезные данные.
🚀 Что делать
Если нужно быстро находить очень редкие статусы (например, 1% ошибок в логах), создавай частичный индекс:
Он займет минимум места и будет реально использоваться.
💡 Индекс полезен, только когда он отсеивает подавляющее большинство строк, а не делит их пополам.
Кажется логичным: если в запросах часто есть
WHERE is_active = true, на эту колонку нужен индекс. Но на деле база его проигнорирует, а ты лишь замедлишь работу системы.⚙️ Почему база его не использует
Индексу важно разнообразие значений (кардинальность). Представь предметный указатель в конце книги: если слово встречается на 90% страниц, проще пролистать всю книгу целиком.
Оптимизатор рассуждает так же. Если значений всего два (true/false), он выберет полное сканирование таблицы (Seq Scan). Читать данные подряд намного быстрее, чем постоянно прыгать туда-сюда между индексом и таблицей.
📉 В чем реальный вред
Проигнорированный индекс становится мертвым грузом:
🔹 При каждом
INSERT, UPDATE и DELETE базе приходится тратить время на обновление этой ненужной структуры.🔹 Индекс впустую съедает место на диске и вытесняет из оперативной памяти действительно полезные данные.
🚀 Что делать
Если нужно быстро находить очень редкие статусы (например, 1% ошибок в логах), создавай частичный индекс:
CREATE INDEX idx_errors ON logs(status) WHERE status = 'error';
Он займет минимум места и будет реально использоваться.
💡 Индекс полезен, только когда он отсеивает подавляющее большинство строк, а не делит их пополам.
❤14👍12🤯3
🙈 Повесил индекс, а база его игнорит
Ты создал индекс на колонку
⚙️ Почему это происходит
Индекс работает как алфавитный указатель в конце книги. Он идеален, если тебе нужно найти 5 строк из миллиона. База быстро находит ссылки и точечно забирает данные.
📉 Когда Full Scan быстрее
Если ты ищешь активных пользователей (например,
🔹 Читать таблицу подряд (Full Scan) — это очень быстро. Как читать книгу страницу за страницей.
🔹 Использовать индекс для 85% строк — это сотни тысяч хаотичных прыжков туда-сюда за каждой отдельной строкой (Random I/O). Это слишком медленно, базе гораздо дешевле прочитать всё подряд и отфильтровать лишнее.
🚀 Что делать
🔸 Не строй индексы на колонки, где всего пара вариантов значений (статусы, пол, флаги).
🔸 Если часто ищешь редкие статусы (например, ошибки), используй частичный индекс:
💡 Индекс нужен для точечного поиска редких данных, а не для перекапывания всей таблицы.
Ты создал индекс на колонку
status, запускаешь поиск, а EXPLAIN нагло выдаёт Seq Scan. Кажется, база сломалась, но на самом деле она спасает твоё время.⚙️ Почему это происходит
Индекс работает как алфавитный указатель в конце книги. Он идеален, если тебе нужно найти 5 строк из миллиона. База быстро находит ссылки и точечно забирает данные.
📉 Когда Full Scan быстрее
Если ты ищешь активных пользователей (например,
is_active = true), а их в таблице 85%, индекс становится врагом оптимизатора.🔹 Читать таблицу подряд (Full Scan) — это очень быстро. Как читать книгу страницу за страницей.
🔹 Использовать индекс для 85% строк — это сотни тысяч хаотичных прыжков туда-сюда за каждой отдельной строкой (Random I/O). Это слишком медленно, базе гораздо дешевле прочитать всё подряд и отфильтровать лишнее.
🚀 Что делать
🔸 Не строй индексы на колонки, где всего пара вариантов значений (статусы, пол, флаги).
🔸 Если часто ищешь редкие статусы (например, ошибки), используй частичный индекс:
CREATE INDEX idx_errors ON users(status) WHERE status = 'error';
💡 Индекс нужен для точечного поиска редких данных, а не для перекапывания всей таблицы.
👍10❤4🔥2🗿2
🛑 Как Materialized View может повесить продакшен
Ты создал материализованное представление, чтобы ускорить тяжёлые запросы. Но в момент обновления данных приложение вдруг замирает, а пользователи видят бесконечную загрузку.
⚙️ Почему всё зависло
Обычная команда
🔹 Она вешает эксклюзивную блокировку. База полностью запрещает чтение, пока собирает новые данные. Это как закрыть магазин на переучёт — внутрь никого не пускают.
🚀 Как обновить без даунтайма
Чтобы отдавать пользователям старые данные, пока база в фоне строит новые, используй эту команду:
⚠️ Главный подвох
Слово
🔸 Обязательное условие: на вьюшке должен быть создан уникальный индекс (например, по ID). Без него запрос завершится с ошибкой.
💡 Уникальный индекс плюс обновление в фоне — и пользователи больше не увидят зависаний.
Ты создал материализованное представление, чтобы ускорить тяжёлые запросы. Но в момент обновления данных приложение вдруг замирает, а пользователи видят бесконечную загрузку.
⚙️ Почему всё зависло
Обычная команда
REFRESH MATERIALIZED VIEW работает очень грубо. 🔹 Она вешает эксклюзивную блокировку. База полностью запрещает чтение, пока собирает новые данные. Это как закрыть магазин на переучёт — внутрь никого не пускают.
🚀 Как обновить без даунтайма
Чтобы отдавать пользователям старые данные, пока база в фоне строит новые, используй эту команду:
REFRESH MATERIALIZED VIEW CONCURRENTLY my_report;
⚠️ Главный подвох
Слово
CONCURRENTLY не сработает просто так. Базе нужно точно понимать, как сопоставлять старые и новые строки при фоновом обновлении. 🔸 Обязательное условие: на вьюшке должен быть создан уникальный индекс (например, по ID). Без него запрос завершится с ошибкой.
CREATE UNIQUE INDEX ON my_report (id);
💡 Уникальный индекс плюс обновление в фоне — и пользователи больше не увидят зависаний.
👍12🔥3🤯2❤1
🪓 Убили индекс одной функцией: почему YEAR(date) тормозит базу
Ты создал идеальный индекс по дате, но запрос всё равно работает целую вечность. Причина кроется всего в одной функции.
⚙️ Почему база игнорирует индекс
🔹 Как только ты пишешь
🔹 Она не может искать по индексу (как по алфавитному указателю в книге), потому что ей нужно сначала вычислить год для каждой строки таблицы.
🔹 Итог — долгое полное сканирование (Seq Scan), даже если нужных строк всего пара штук.
🚀 Как починить (правило SARG)
Чтобы индекс сработал, колонка должна оставаться «чистой» — без математики и функций. Перенеси все условия в правую часть от знака равенства.
🔸 Плохо: индекс сломается
🔸 Хорошо: моментальный поиск
💡 Оставляй проиндексированную колонку в одиночестве слева от условия, и база ответит моментально.
Ты создал идеальный индекс по дате, но запрос всё равно работает целую вечность. Причина кроется всего в одной функции.
⚙️ Почему база игнорирует индекс
🔹 Как только ты пишешь
WHERE YEAR(order_date) = 2023, база перестаёт видеть исходные значения дат.🔹 Она не может искать по индексу (как по алфавитному указателю в книге), потому что ей нужно сначала вычислить год для каждой строки таблицы.
🔹 Итог — долгое полное сканирование (Seq Scan), даже если нужных строк всего пара штук.
🚀 Как починить (правило SARG)
Чтобы индекс сработал, колонка должна оставаться «чистой» — без математики и функций. Перенеси все условия в правую часть от знака равенства.
🔸 Плохо: индекс сломается
SELECT * FROM orders
WHERE YEAR(order_date) = 2023;
🔸 Хорошо: моментальный поиск
SELECT * FROM orders
WHERE order_date >= '2023-01-01' AND order_date < '2024-01-01';
💡 Оставляй проиндексированную колонку в одиночестве слева от условия, и база ответит моментально.
❤12👍8🔥4
🪞 Иллюзия скорости: почему обычный VIEW не ускорит запросы
Спрятал огромный JOIN в представление, чтобы база работала быстрее? Плохие новости: обычный VIEW вообще ничего не кэширует.
⚙️ Как это работает на самом деле
Многие путают представление с физической таблицей. Но обычный VIEW — это просто текстовый макрос.
🔹 Каждый раз, когда ты делаешь
🔹 Никакие результаты на диск не сохраняются. Все тяжёлые вычисления будут происходить заново при каждом обращении.
⚠️ Опасность «матрёшки»
Самая частая ошибка — строить одни вьюшки поверх других.
🔸 База вынуждена разворачивать этот клубок в один гигантский запрос.
🔸 Планировщик запросов теряется в абстракциях и может выбрать худший план выполнения. То, что должно работать секунду, выполняется часами.
🚀 Что делать?
🔹 Для реального ускорения и сохранения результата на диск используй:
🔹 Обычный VIEW оставляй только для удобства: чтобы скрыть сложную логику от других разработчиков или упростить чтение кода.
💡 Обычное представление создано для чистоты кода, а не для производительности.
Спрятал огромный JOIN в представление, чтобы база работала быстрее? Плохие новости: обычный VIEW вообще ничего не кэширует.
⚙️ Как это работает на самом деле
Многие путают представление с физической таблицей. Но обычный VIEW — это просто текстовый макрос.
🔹 Каждый раз, когда ты делаешь
SELECT * FROM my_view, база берёт исходный запрос и выполняет его с нуля.🔹 Никакие результаты на диск не сохраняются. Все тяжёлые вычисления будут происходить заново при каждом обращении.
⚠️ Опасность «матрёшки»
Самая частая ошибка — строить одни вьюшки поверх других.
🔸 База вынуждена разворачивать этот клубок в один гигантский запрос.
🔸 Планировщик запросов теряется в абстракциях и может выбрать худший план выполнения. То, что должно работать секунду, выполняется часами.
🚀 Что делать?
🔹 Для реального ускорения и сохранения результата на диск используй:
CREATE MATERIALIZED VIEW my_cache AS
SELECT ...
🔹 Обычный VIEW оставляй только для удобства: чтобы скрыть сложную логику от других разработчиков или упростить чтение кода.
💡 Обычное представление создано для чистоты кода, а не для производительности.
❤7👍6🔥1
22-23 сентября приглашаем на АЛЬФА ВААА{АИ}ЙЙЙБ ХАКАТОН. Создавайте проект высоконагруженного прокси, соревнуйтесь за 2,3 миллиона рублей, общайтесь в комьюнити топовых вайб-кодеров.
Всех участников пригласим 30 сентября на АЛЬФА ВААА{АИ}ЙЙЙБ МИТАП. Узнаем, кто из финалистов получит миллион, зажжём на техно-рейве с группой ЛАУД и проведём ток-шоу про нейросети.
Скорее регистрируйтесь
Всех участников пригласим 30 сентября на АЛЬФА ВААА{АИ}ЙЙЙБ МИТАП. Узнаем, кто из финалистов получит миллион, зажжём на техно-рейве с группой ЛАУД и проведём ток-шоу про нейросети.
Скорее регистрируйтесь
❤6👍3🔥3