Как эффективно запросить БД, когда нужно построить постраничное представление для большой таблицы и присоединить дополнительные детали из маленькой?

Я пытаюсь понять типичные подходы для следующих распространенных ситуаций, возникающих при разработке на Rails или Django.

Пример истории пользователя

Я хочу фильтровать и сортировать покупки, а затем разворачивать подробную информацию о некоторых купленных товарах, щелкая по их строкам и просматривая детали прямо там. При необходимости переходить на следующие страницы.

Детали модели данных

Большая таблица с покупками (миллионы).

Маленькая таблица с данными о товарах (тысячи).

Только один продукт на одну покупку.

Главный вопрос

Как организовать обработку такого запроса, чтобы добиться наилучшей производительности? Влияет ли на это фреймворк ORM?

Скорее всего, существует множество "это зависит". Я буду благодарен, если вы укажете на них.

Потенциальные подходы

  1. get everything needed for the page in one query then render as requested
  2. get filtered and sorted purchases in one query, send individual queries for details

Более мелкие вопросы

  • Даже когда мы предоставляем все данные в одном HTTP-запросе: есть ли случай разделить запросы на два? Сначала WHERE's, ORDER, OFFSET и LIMIT для большой таблицы. Затем перейдите с результатом к маленькой таблице для присоединения.
  • Если это делается в одном запросе: является ли обычным подходом сначала выполнить подмножество с помощью WITH и только затем выполнить объединение?
  • Правильно ли я понимаю, что обычно ORM-конструктор запросов делает один большой запрос, поэтому если нужно оптимизировать SQL-запросы, то нужно обойти ORM?
  • Есть ли случай, когда подход с использованием логики бэкенда лучше по сравнению с оптимизированным SQL-запросом? Например, добавление деталей в цикле?
  • Упрощенные примеры

    Это

    SELECT P.*,
           products.*
    FROM purchases P
    JOIN products ON P.product_id = products.id
    WHERE P.value < 100 AND P.method = 'credit'
    ORDER BY P.date DESC
    OFFSET 100 LIMIT 40;
    

    и соответствующий Rails ORM в качестве примера

    Purchase.join(:product)
            .where('value < ?': 100, method: 'credit')
            .order(date: :desc)
            .offset(100)
            .limit(40)
    

    vs

    WITH P AS (
        SELECT P.*,
        FROM purchases P
        WHERE P.value < 100 AND P.method = 'credit'
        ORDER BY P.date DESC
        OFFSET 100 LIMIT 40)
    SELECT P.*,
           products.*
    FROM P
    JOIN products ON P.product_id = products.id;
    

    Я не знаю, как направить ORM, чтобы сделать это таким образом, не обращаясь к DB дважды.

    Вернуться на верх