我有一个目标表,并且可以使用不同的值基数对不同的列进行过滤来检索我需要从此表中获得的数据集。所有过滤器案例都创建了索引,我在想使用一列作为另一列的过滤器是否存在很大(潜在)性能差异。也许用例子来解释会很简单:
三张桌子 -
account (id, ...)
、product(account_id, id, ...)
和 sales(account_id, product_id, ...)
。
作为某种管理员用户,我想要两个帐户的销售数据,但问题是 - 涉及到许多其他指标,查询变得业务逻辑负担过重。在查询中间,我需要一个 CTE,其中包含销售表中的数据,按
product_id
分组。因此,当加入销售时,我可以在 product_id
上加入产品表,或者,我可以在 account_id
上加入。需要明确的是,这两种情况下的销售数据都是相同的,因为帐户的销售额 = 该帐户所有产品的销售额。加入 product_id
将使用销售表的较高基数索引,加入 account_id
将使用较低的基数索引。我的假设是任何索引都需要遍历/搜索,并且较长的索引需要更多的处理器时间(和内存?)。所以我的问题是,是否值得担心用于过滤的较高与较低(相对于彼此)基数索引列?
查询的开始将类似于:
WITH
fancy_accounts_select AS (
SELECT id AS account_id, ...
),
product_with_all_the_stuff AS (
SELECT id AS product_id, ...
)
我需要选择:
grouped_sales AS (
SELECT s.product_id, other_metrics
FROM sales s
JOIN fancy_accounts_select a ON a.account_id = s.account_id
GROUP BY s.product_id
)
和
grouped_sales AS (
SELECT s.product_id, other_metrics
FROM sales s
JOIN product_with_all_the_stuff p ON p.product_id = s.product_id
GROUP BY s.product_id
)
数据量是您对此类表名称的期望,但我们假设 ~1'000 个帐户、~10'000 个产品、~100'000'000 个销售额。我期望查询执行运行时间接近,因为 Postgres 现在太快了,但想知道是否有一些不太明显的东西我错过了?
我在 Postgres 索引文档页面上找不到太多关于基数的信息,EXPLAIN ANALYZE 结果已经过时了,但我见过的“join on account_id”查询的最低执行时间是 0.5 秒,而“join on product_id”查询的最低执行时间是 0.5 秒。大约 2 秒。
是的,在这种情况下,在所有其他条件相同的情况下,基数越低越好,因为索引会更小。
这意味着加载速度会更快,不会使用太多的缓存空间,并且处理速度会更快。
答案的重要部分是 “在这种情况下”和“在其他条件相同的情况下”。
另一种情况是使用索引来过滤结果,但这还不够。 在这种情况下,基数越高可能越好,因为它可能更具限制性。
并非所有事物都是平等的例子:
所以最终,只有在实际负载下对系统进行基准测试才能给您明确的答案。