От автора статьи: Это не рекомендуемый референс-дизайн и не финальная архитектура мечты, а минимальный стартер пак под конкретные ограничения: бюджет, сроки и доступное железо. Если отбросить академическую картинку идеального Clos, схема остаётся полностью рабочей для нашего профиля нагрузки. В такой модели отказ одного Leaf не означает остановку серверов, потому что второй линк остаётся рабочим. Отказ Spine тоже не равен остановке клиентского сервиса, потому что Leaf'ы не завязаны на общий IRB, EVPN multihoming/ESI-LAG и общий L2-сегмент, который надо синхронно обслуживать с двух сторон. Это минимальная промежуточная схема, которая переживает реалистичные аварийные сценарии и не требует покупать дополнительное железо, поэтому я считаю что, она вполне имеет право на жизнь. И вопрос скорее не в том, "что же тут не так", а в том, какая цена у более правильной схемы на старте и какой риск она реально закрывает.
По словам автора статьи, да, один Spine — это осознанный компромисс, а не эталонная целевая схема. Но в нашем конкретном дизайне его отказ не означает остановку клиентского сервиса. Даже если вынести за скобки прямой горизонтальный линк между Leaf, который мы оставили как аварийную страховку, сама схема не слишком чувствительна к потере синхронизации Leaf между собой. У нас нет общих IRB-интерфейсов, нет EVPN multihoming/ESI-LAG и нет сценария, где два Leaf должны синхронно обслуживать один общий L2-сегмент. Каждый Leaf имеет собственный default-route, независимый BGP-пиринг с апстримом и отдельную связность с внутренними route-reflector'ами, которые отвечают за достижимость виртуальных машин. Поэтому при проблеме со Spine мы в первую очередь теряем оптимальность части путей и балансировку исходящего трафика в сторону апстрима, а не саму возможность пересылки клиентского трафика. Ну и да, второй Spine нужен и остаётся логичным следующим шагом при увеличении количества Leaf'ов.
Спасибо за конструктивный комментарий! Действительно, термин «антипаттерн» может звучать немного категорично. Я ориентировался прежде всего на начинающих разработчиков и хотел выделить такие кейсы как «красные флаги» — сигналы для того, чтобы заглянуть в EXPLAIN ANALYZE и проверить свои гипотезы. Обязательно добавлю в выводы оговорку про осознанное использование нескольких CTE. Благодарю — замечание полезное.
P.S. Кстати, «любовь» PostgreSQL к сортировкам и отличие от Oracle/MPP — отличная тема для отдельной статьи. Было бы здорово увидеть ваш материал на Habr.
Отвечает автор: Полезнее всего здесь получился чек-лист по плану, особенно связка actual rows, loops и temp written. Я бы добавил еще одну проверку перед переписыванием CTE: сравнить план не на одном литерале, а на нескольких значениях с разной селективностью. В приложении тот же SQL часто выполняется как prepared statement, и после нескольких запусков PostgreSQL может перейти от custom plan к generic plan. Тогда пример с узким диапазоном работает через индекс, а широкий диапазон получает тот же усредненный план и внезапно проседает уже в проде. Поэтому рядом с EXPLAIN ANALYZE полезно смотреть распределение значений, расхождение estimated/actual rows и при подозрении сравнивать force_custom_plan с force_generic_plan. Проверяли ли вы эти четыре примера в режиме prepared statements, особенно первый с диапазоном customer_id?
Приветствуем! Нам жаль, что вам пришлось столкнуться с такой ситуацией.
Действительно, летом 2026 года в дата-центре нашей локации «Амстердам» (Qupra DC2) произошла серия отказов системы охлаждения, что послужило причиной недоступности серверов. Пострадавшие клиенты могут получить компенсации и бонусы. Подробнее о происшествии и мерах помощи рассказали в подробном разборе.
Чтобы подобного не повторилось, мы приняли решение о переезде в более стабильный ДЦ. Сейчас ведем работы: обо всем рассказываем в своем тг-канале.
Приветствуем! Спасибо за детальный разбор, в FirstVDS всегда рады аргументированной критике.
Но хотим уточнить нюансы по методологии обзора. Десктопная AIDA64 не подходит для оценки VDS на виртуализации KVM: обозначенная задержка L3-кэша на деле является откликом планировщика гипервизора. А тесты GPGPU без видеокарты оторваны от реальных серверных задач.
Давайте протестируем VPS на реальной нагрузке? Мы готовы бесплатно выдать более мощный инстанс или продлить текущий. Предлагаем развернуть ваш проект, прогнать yabs.sh или нагрузить БД через sysbench. Напишите, пожалуйста, нам в личные сообщения на Хабре или в поддержку для маркетинга — сделаем честный тест, результаты которого не стыдно добавить в ваш рейтинг.
Здравствуйте! Сейчас проверки у нас выполняются из двух российских локаций: Москва и Санкт-Петербург. Это позволяет оценивать доступность сайта из локальных точек внутри РФ, а не из зарубежных дата-центров, где кратковременные проблемы на маршруте действительно могут давать ложные срабатывания.
Дополнительно у нас используется время жизни инцидента: если недоступность была кратковременной и длилась всего несколько секунд, такой сбой не сразу переходит в инцидент. Это помогает отсекать ложные срабатывания, связанные с временными сетевыми проблемами на маршруте, у провайдера или в DNS. Если же проблема держится дольше заданного порога и/или подтверждается из нескольких точек, это уже более похоже на реальную недоступность сайта.
Иван, приятно, что вы так переживаете о наших читателях. За идею с дисклеймером спасибо, добавим в статью. Но мы не считаем аудиторию наших читателей настолько неопытными, чтобы она не отличила продакшен от авторского опыта с пометкой mvp.
Иван, здравствуйте. Мы не только проверяем статьи с внутренними экспертами, но и поддерживаем авторов, которые пишут самостоятельно без использования ИИ и хотят делиться не только суперидеальными проектами, но и промежуточными результатами своей работы, вроде mvp, о чем прямо говорят в статье. Делают это для того, чтобы иметь возможность получить профессиональные советы и конструктивную критику коллег. И дальше продолжить работу над проектом. О чем тоже было сказано в статье. Гитлаб автора, понятное дело, на совести автора.
В нашем случае deep buffer на Spine не был требованием первого дня. Это был задел под нормальную архитектуру площадки и унификацию с другими нашими локациями. На старте, честно говоря, Spine сам по себе был почти избыточен: при одном или двух Leaf фабрика ещё не раскрывается как полноценная Clos-топология. Но мы строили площадку с понятным путём роста.
Логика такая: Leaf у нас — это коммутатор доступа, shallow-buffer. К нему подключены гипервизоры, а модель подключения построена через L3 и ECMP. Для server-facing роли это нормально. Spine, наоборот, выбирался как deep-buffer-коммутатор, потому что в перспективе именно на нём сходятся потоки от разных Leaf. Там выше риск microbursts: коротких всплесков, когда несколько входящих направлений одновременно пытаются выгрузиться в один выходной порт. Большой буфер помогает переживать такие всплески без лишних потерь пакетов, особенно в сценариях с DCI, сетевыми хранилищами, бэкапами и другим bulk-трафиком. Поэтому на старте deep buffer действительно не был жизненно необходим. Но с учётом будущего роста, DCI и типовой архитектуры наших локаций мы предпочли сразу поставить Spine того класса, который не придётся менять при первом же расширении.
"Спасибо за комментарий! Да, при сравнении литерала varchar = bigint PostgreSQL выдаст ошибку. В примере я описывал ситуацию, которая чаще всего встречается в приложениях — когда значение приходит как параметр, и ORM передаёт его в «неправильном» типе (обычно как BIGINT). В этом случае PostgreSQL уже приводит колонку к типу параметра, и индекс перестаёт использоваться.
Действительно обновление статистики помогает, но не всегда спасает. Есть запросы, где планировщик в принципе не может выбрать идеальный план, и тогда без ручного вмешательства не обойтись. Просто в рамках гайда я сосредоточился на более типичных сценариях, с которыми чаще всего сталкиваются начинающие."
Спасибо за комментарий — вы верно подметили важный технический нюанс. В статье автор сознательно сосредоточился на базовых приёмах оптимизации: как по возможности уйти от Seq Scan к Index Scan, проверить актуальность статистики и сделать простой рефакторинг запросов. Эти шаги дают первые ощутимые улучшения без погружения в тонкости внутренних процессов СУБД. Тема Index Only Scan и его деградации из-за устаревшей visibility map, на мой взгляд, — уже более продвинутый уровень. Важность работы autovacuum автора отметил, но детали его механизмов оставил за рамками, чтобы не перегружать читателя на начальном этапе.
Спасибо за комментарий. В этой статье автор больше сфокусировался на инструментах поиска потенциально тяжёлых запросов, оставив оценку их реальной критичности на усмотрение разработчика или DBA. А так, вы верно подметили: медленный запрос не всегда является проблемой — например, в случае аналитических отчётов или batch-обработки длительное выполнение может быть ожидаемым.
От автора статьи: Это не рекомендуемый референс-дизайн и не финальная архитектура мечты, а минимальный стартер пак под конкретные ограничения: бюджет, сроки и доступное железо. Если отбросить академическую картинку идеального Clos, схема остаётся полностью рабочей для нашего профиля нагрузки. В такой модели отказ одного Leaf не означает остановку серверов, потому что второй линк остаётся рабочим. Отказ Spine тоже не равен остановке клиентского сервиса, потому что Leaf'ы не завязаны на общий IRB, EVPN multihoming/ESI-LAG и общий L2-сегмент, который надо синхронно обслуживать с двух сторон. Это минимальная промежуточная схема, которая переживает реалистичные аварийные сценарии и не требует покупать дополнительное железо, поэтому я считаю что, она вполне имеет право на жизнь. И вопрос скорее не в том, "что же тут не так", а в том, какая цена у более правильной схемы на старте и какой риск она реально закрывает.
По словам автора статьи, да, один Spine — это осознанный компромисс, а не эталонная целевая схема. Но в нашем конкретном дизайне его отказ не означает остановку клиентского сервиса. Даже если вынести за скобки прямой горизонтальный линк между Leaf, который мы оставили как аварийную страховку, сама схема не слишком чувствительна к потере синхронизации Leaf между собой. У нас нет общих IRB-интерфейсов, нет EVPN multihoming/ESI-LAG и нет сценария, где два Leaf должны синхронно обслуживать один общий L2-сегмент. Каждый Leaf имеет собственный default-route, независимый BGP-пиринг с апстримом и отдельную связность с внутренними route-reflector'ами, которые отвечают за достижимость виртуальных машин. Поэтому при проблеме со Spine мы в первую очередь теряем оптимальность части путей и балансировку исходящего трафика в сторону апстрима, а не саму возможность пересылки клиентского трафика. Ну и да, второй Spine нужен и остаётся логичным следующим шагом при увеличении количества Leaf'ов.
Ответ автора:
Спасибо за конструктивный комментарий! Действительно, термин «антипаттерн» может звучать немного категорично. Я ориентировался прежде всего на начинающих разработчиков и хотел выделить такие кейсы как «красные флаги» — сигналы для того, чтобы заглянуть в EXPLAIN ANALYZE и проверить свои гипотезы. Обязательно добавлю в выводы оговорку про осознанное использование нескольких CTE. Благодарю — замечание полезное.
P.S. Кстати, «любовь» PostgreSQL к сортировкам и отличие от Oracle/MPP — отличная тема для отдельной статьи. Было бы здорово увидеть ваш материал на Habr.
Отвечает автор:
Полезнее всего здесь получился чек-лист по плану, особенно связка actual rows, loops и temp written. Я бы добавил еще одну проверку перед переписыванием CTE: сравнить план не на одном литерале, а на нескольких значениях с разной селективностью. В приложении тот же SQL часто выполняется как prepared statement, и после нескольких запусков PostgreSQL может перейти от custom plan к generic plan. Тогда пример с узким диапазоном работает через индекс, а широкий диапазон получает тот же усредненный план и внезапно проседает уже в проде. Поэтому рядом с EXPLAIN ANALYZE полезно смотреть распределение значений, расхождение estimated/actual rows и при подозрении сравнивать force_custom_plan с force_generic_plan. Проверяли ли вы эти четыре примера в режиме prepared statements, особенно первый с диапазоном customer_id?
Приветствуем! Нам жаль, что вам пришлось столкнуться с такой ситуацией.
Действительно, летом 2026 года в дата-центре нашей локации «Амстердам» (Qupra DC2) произошла серия отказов системы охлаждения, что послужило причиной недоступности серверов. Пострадавшие клиенты могут получить компенсации и бонусы. Подробнее о происшествии и мерах помощи рассказали в подробном разборе.
Чтобы подобного не повторилось, мы приняли решение о переезде в более стабильный ДЦ. Сейчас ведем работы: обо всем рассказываем в своем тг-канале.
Приветствуем! Спасибо за детальный разбор, в FirstVDS всегда рады аргументированной критике.
Но хотим уточнить нюансы по методологии обзора. Десктопная AIDA64 не подходит для оценки VDS на виртуализации KVM: обозначенная задержка L3-кэша на деле является откликом планировщика гипервизора. А тесты GPGPU без видеокарты оторваны от реальных серверных задач.
Давайте протестируем VPS на реальной нагрузке? Мы готовы бесплатно выдать более мощный инстанс или продлить текущий. Предлагаем развернуть ваш проект, прогнать yabs.sh или нагрузить БД через sysbench. Напишите, пожалуйста, нам в личные сообщения на Хабре или в поддержку для маркетинга — сделаем честный тест, результаты которого не стыдно добавить в ваш рейтинг.
Здравствуйте! Сейчас проверки у нас выполняются из двух российских локаций: Москва и Санкт-Петербург. Это позволяет оценивать доступность сайта из локальных точек внутри РФ, а не из зарубежных дата-центров, где кратковременные проблемы на маршруте действительно могут давать ложные срабатывания.
Дополнительно у нас используется время жизни инцидента: если недоступность была кратковременной и длилась всего несколько секунд, такой сбой не сразу переходит в инцидент. Это помогает отсекать ложные срабатывания, связанные с временными сетевыми проблемами на маршруте, у провайдера или в DNS. Если же проблема держится дольше заданного порога и/или подтверждается из нескольких точек, это уже более похоже на реальную недоступность сайта.
Рады, что материал понравился :)
Спасибо, что читаете!
Иван, приятно, что вы так переживаете о наших читателях. За идею с дисклеймером спасибо, добавим в статью. Но мы не считаем аудиторию наших читателей настолько неопытными, чтобы она не отличила продакшен от авторского опыта с пометкой mvp.
Иван, здравствуйте. Мы не только проверяем статьи с внутренними экспертами, но и поддерживаем авторов, которые пишут самостоятельно без использования ИИ и хотят делиться не только суперидеальными проектами, но и промежуточными результатами своей работы, вроде mvp, о чем прямо говорят в статье. Делают это для того, чтобы иметь возможность получить профессиональные советы и конструктивную критику коллег. И дальше продолжить работу над проектом. О чем тоже было сказано в статье. Гитлаб автора, понятное дело, на совести автора.
Спасибо!
Здравствуйте. Вот, что передал автор статьи:
В нашем случае deep buffer на Spine не был требованием первого дня. Это был задел под нормальную архитектуру площадки и унификацию с другими нашими локациями. На старте, честно говоря, Spine сам по себе был почти избыточен: при одном или двух Leaf фабрика ещё не раскрывается как полноценная Clos-топология. Но мы строили площадку с понятным путём роста.
Логика такая: Leaf у нас — это коммутатор доступа, shallow-buffer. К нему подключены гипервизоры, а модель подключения построена через L3 и ECMP. Для server-facing роли это нормально. Spine, наоборот, выбирался как deep-buffer-коммутатор, потому что в перспективе именно на нём сходятся потоки от разных Leaf. Там выше риск microbursts: коротких всплесков, когда несколько входящих направлений одновременно пытаются выгрузиться в один выходной порт. Большой буфер помогает переживать такие всплески без лишних потерь пакетов, особенно в сценариях с DCI, сетевыми хранилищами, бэкапами и другим bulk-трафиком. Поэтому на старте deep buffer действительно не был жизненно необходим. Но с учётом будущего роста, DCI и типовой архитектуры наших локаций мы предпочли сразу поставить Spine того класса, который не придётся менять при первом же расширении.
Отвечает автор:
Благодарю за уточнение!
В дата-центре Qupra DC2 проблема с чиллерами. Устраняем. Следить за статусом можно тут — https://firstvds.live.
Спасибо за комментарий. Добавили ссылку.
Добрый день!
Отвечает автор:
"Спасибо за комментарий! Да, при сравнении литерала varchar = bigint PostgreSQL выдаст ошибку. В примере я описывал ситуацию, которая чаще всего встречается в приложениях — когда значение приходит как параметр, и ORM передаёт его в «неправильном» типе (обычно как BIGINT). В этом случае PostgreSQL уже приводит колонку к типу параметра, и индекс перестаёт использоваться.
Действительно обновление статистики помогает, но не всегда спасает. Есть запросы, где планировщик в принципе не может выбрать идеальный план, и тогда без ручного вмешательства не обойтись. Просто в рамках гайда я сосредоточился на более типичных сценариях, с которыми чаще всего сталкиваются начинающие."
Спасибо за комментарий — вы верно подметили важный технический нюанс. В статье автор сознательно сосредоточился на базовых приёмах оптимизации: как по возможности уйти от Seq Scan к Index Scan, проверить актуальность статистики и сделать простой рефакторинг запросов. Эти шаги дают первые ощутимые улучшения без погружения в тонкости внутренних процессов СУБД. Тема Index Only Scan и его деградации из-за устаревшей visibility map, на мой взгляд, — уже более продвинутый уровень. Важность работы autovacuum автора отметил, но детали его механизмов оставил за рамками, чтобы не перегружать читателя на начальном этапе.
так, вроде теперь должно заработать, посмотрите, пожалуйста)
Спасибо за комментарий. В этой статье автор больше сфокусировался на инструментах поиска потенциально тяжёлых запросов, оставив оценку их реальной критичности на усмотрение разработчика или DBA. А так, вы верно подметили: медленный запрос не всегда является проблемой — например, в случае аналитических отчётов или batch-обработки длительное выполнение может быть ожидаемым.