Как создать сводную таблицу (витрину данных), которая улучшит производительность диаграммы? - PullRequest
0 голосов
/ 08 апреля 2020

Я создал таблицу с именем user_preferences , где пользовательские настройки сгруппированы по user_id и month .

Table :

enter image description here

Каждый месяц я собираю все user_ids и назначаю все предпочтения:

  • город
  • район
  • количество номеров
  • максимальная цена, которую они могут потратить

План предполагает отображение графика, показывающего намерения пользователей по покупкам, подобные этой : enter image description here

Синяя линия - количество заинтересованных пользователей для выбранных значений в фильтрах.

График должен включать фильтрацию по параметрам, отмеченным красным. То, что вы видите выше, является упрощенной формой для разъяснения предмета. На самом деле, есть еще много пользователей. Каждый месяц таблица увеличивается на несколько сотен тысяч записей. Запрос SQL для извлечения данных (подачи) для диаграммы длится до 50 секунд. Это слишком много - я не могу себе этого позволить.

Итак, мне нужно создать таблицу (таблица / агрегация / витрина данных), куда я смогу вставить ранее рассчитанное число заинтересованных пользователи для всех комбинаций. Благодаря этому конечному пользователю не придется ждать подсчета данных.

Подробности ниже:

enter image description here

Теперь вопрос - как создать такую ​​таблицу в PostgreSQL? Я знаю, как написать запрос SQL, который вычислит конкретный пример c.

SELECT
 month,
 count(DISTINCT user_id) interested_users
FROM 
 user_preferences
WHERE
 month BETWEEN '2020-01' AND '2020-03'
 AND city = 'Madrid'
 AND district = 'Latina'
 AND rooms IN (1,2)
 AND price_max BETWEEN 400001 AND 500000
GROUP BY 
 1

Вопрос - как рассчитать все возможные комбинации? Могу ли я написать несколько вложенных l oop в SQL?

topi c очень важен для меня, я думаю, что он также будет полезен для других в будущем. Буду крайне признателен за любые советы.

1 Ответ

0 голосов
/ 08 апреля 2020

Ну, основываясь на вашем запросе, у вас есть следующие фильтры:

  • месяц
  • город
  • distirct
  • номера
  • price_max

Вы можете попробовать создать представление со следующей структурой:

SELECT month
     ,city
     ,distirct
     ,rooms
     ,price_max
     ,count(DISTINCT user_id)
FROM  user_preferences
GROUP BY month
        ,city
        ,distirct
        ,rooms
        ,price_max

Вы можете сделать это представление материализованным . Таким образом, запрос за представлением не будет выполнен при запросе. Он будет вести себя как стол.

Когда вы добавляете новые записи в базовую таблицу, вам необходимо обновить sh представление (к сожалению, posgre sql не поддерживает авто-refre sh, как и другие):

REFRESH MATERIALIZED VIEW my_view;

или вы можете запланировать задачу.

Если вы используете только точный поиск для каждого поля, это будет работать. Но в вашем примере у вас есть такие критерии, как:

month BETWEEN '2020-01' AND '2020-03'
AND rooms IN (1,2)
AND price_max BETWEEN 400001 AND 500000

В таких случаях я обычно пишу тот же запрос, но SUM данные из материализованного представления. В вашем случае вы используете DISTINCT, и это может привести к counting пользователю несколько раз.

Если это проблема, вам нужно пересчитать слишком много комбинаций, и я сомневаюсь, что это ответ. Кроме того, вы можете попытаться нормализовать ваши данные - это улучшит производительность агрегации.

...