Логотип YeaHub

База вопросов

Собеседования

Тренажёр

База ресурсов

Обучение

Навыки

Войти

Выбери, каким будет IT завтра — вместе c нами!

YeaHub — это полностью открытый проект, призванный объединить и улучшить IT-сферу. Наш исходный код доступен для просмотра на GitHub. Дизайн проекта также открыт для ознакомления в Figma.

© 2026 YeaHub

Документы

Медиа

Назад
Вопрос про Postgres: denormalization, performance, consistency, update strategy

Денормализация для уменьшения JOIN-запросов — как быть, если данные часто меняются (например, остатки товаров)?

Этот вопрос рассматривает проблему денормализации часто изменяемых данных и стратегии поддержания актуальности.

Короткий ответ

Для часто изменяемых данных применяются стратегии асинхронного обновления денормализованных полей через триггеры, очереди задач или materialized views. Вместо реального времени можно использовать near-real-time обновление с задержкой. Для остатков товаров эффективно кэширование актуальных значений с инвалидацией при изменениях. Также можно разделять "горячие" часто изменяемые данные и "холодные" статические данные.

Длинный ответ

Денормализация динамических данных требует специальных подходов для поддержания консистентности.

Проблемы часто изменяемых данных:

  • Расхождение между оригинальными и денормализованными данными

  • Высокая нагрузка от постоянных обновлений

  • Сложность обеспечения ACID

Стратегии решения:

  1. Асинхронное обновление:

// При изменении остатков
class StockService {
    public function updateStock($productId, $quantity) {
        // Основное обновление
        DB::table('products')
            ->where('id', $productId)
            ->update(['stock' => $quantity]);
        
        // Асинхронное обновление денормализованных данных
        UpdateDenormalizedStock::dispatch($productId);
    }
}
  1. Триггеры в базе данных:

CREATE TRIGGER update_product_search 
AFTER UPDATE ON products
FOR EACH ROW
BEGIN
    UPDATE product_search 
    SET stock = NEW.stock,
        updated_at = NOW()
    WHERE product_id = NEW.id;
END;
  1. Materialized Views (PostgreSQL):

CREATE MATERIALIZED VIEW product_stats AS
SELECT p.id, p.name, p.stock, c.name as category_name
FROM products p
JOIN categories c ON p.category_id = c.id;

-- Обновление по расписанию
REFRESH MATERIALIZED VIEW product_stats;
  1. Кэширование с TTL:

function getProductWithStock($productId) {
    return Cache::remember("product:{$productId}:stock", 60, function() use ($productId) {
        return Product::with('category')->find($productId);
    });
}

Компромиссы точности:

  • Real-time: высокая точность, низкая производительность

  • Near-real-time: баланс точности и производительности

  • Batch updates: высокая производительность, задержка данных

Уровень

  • Рейтинг:

    3

  • Сложность:

    8

Навыки

  • Postgres

    Postgres

Ключевые слова

#denormalization

#performance

#consistency

#update strategy

Подпишись на PHP Developer в телеграм