如何创建可以提高图表性能的聚合表(数据集市)?

Posted

技术标签:

【中文标题】如何创建可以提高图表性能的聚合表(数据集市)?【英文标题】:How to create an aggregate table (data mart) that will improve chart performance? 【发布时间】:2020-04-08 07:53:49 【问题描述】:

我创建了一个名为 user_preferences 的表,其中用户首选项按 user_idmonth 分组。

表格

每个月我都会收集所有 user_ids 并分配所有偏好:

城市 区 房间数 他们可以花费的最高价格

该计划假设显示一个图表,显示用户的购物意图,如下所示:

蓝线是对过滤器中所选值感兴趣的用户数。

图表应启用按红色标记的参数进行过滤。 您在上面看到的是用于澄清主题的简化形式。事实上,还有更多的用户。每个月,该表都会增加数十万条记录。为图表检索数据(馈送)的 SQL 查询最长持续 50 秒。太多了——我买不起。

因此,我需要创建一个表(表/聚合/数据集市),我将能够在其中插入先前计算的 感兴趣的用户数 用于所有组合。多亏了这一点,最终用户不必等待数据计数。

详情如下:

现在的问题是 - 如何在 PostgreSQL 中创建这样的表? 我知道如何编写将计算特定示例的 SQL 查询。

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

问题是——如何计算所有可能的组合?我可以在 SQL 中编写多个嵌套循环吗?

这个话题对我来说非常重要,我认为它对未来的其他人也很有用。 我将非常感谢任何提示。

【问题讨论】:

你能显示你当前的查询吗? 是的,SQL 中的示例查询用于添加到描述中的喂食图表 为什么要统计DISTINCT 用户?这很重要吗? 我想知道有多少人对给定类型的房产感兴趣。一位客户可能对不同地点的多种类型感兴趣。 【参考方案1】:

好吧,根据您的查询,您有以下过滤器:

月 城市 区 房间 price_max

您可以尝试使用以下结构创建视图:

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

您可以将此视图设为materialized。所以,视图后面的查询在查询时不会被执行。它将表现得像桌子。

当您向基表添加新记录时,您需要刷新视图(不幸的是,posgresql 不像其他的那样支持自动刷新):

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 一个用户多次使用。

如果这是一个问题,您需要预先计算太多的组合,我怀疑这就是答案。或者,您可以尝试规范化您的数据 - 这将提高聚合的性能。

【讨论】:

以上是关于如何创建可以提高图表性能的聚合表(数据集市)?的主要内容,如果未能解决你的问题,请参考以下文章

数据仓库中事实表的复合索引 - 数据集市

对数据集市中的外键列使用 NULL 是不是有任何性能影响

Inmon 数据集市与 Kimball 数据集市

SQL Server的优点与缺点

如何理解数据库的索引?

如何创建数据集市