选择性谓词下推查看
Posted
技术标签:
【中文标题】选择性谓词下推查看【英文标题】:Selective Predicate Pushdown To View 【发布时间】:2022-01-01 23:29:12 【问题描述】:我有一个经常更新的大型列存储表。我不会将更新直接摄取到源表中,因为在大多数情况下,这会导致少量更新导致全表微分区重建。相反,我将更新流式传输到更新表,并在查询时将两者结合起来。在实践中,这很有效。
所以把事情简化一下,我会把它放在一个视图中users_view
。
CREATE OR REPLACE VIEW users_view AS (
SELECT * FROM users
UNION ALL
SELECT * FROM user_changes
QUALIFY ROW_NUMBER() OVER(
PARTITION BY id
ORDER BY last_updated_at DESC
) = 1
)
users
表和user_changes
表具有相同的方案以及一些分区配置。这样,我可以在视图上使用谓词下推来仅选择正确分区内的用户。假设这是account_id
。
SELECT * FROM users_view
WHERE account_id = 1234
但是users
表比user_changes
表大很多,我想将更多谓词下推到users
表,而不将其他谓词下推到user_changes
表。为什么?因为users
表上的匹配虽然准确率为 98%,但存在误报/误报。需要来自user_changes
的详细信息才能正确设置记录。这在视图之外看起来是这样的:
SELECT * FROM (
SELECT * FROM users
WHERE account_id = 1234 AND city = 'Chicago'
UNION ALL
SELECT * FROM user_changes
WHERE account_id = 1234
QUALIFY ROW_NUMBER() OVER(
PARTITION BY id
ORDER BY last_updated_at DESC
) = 1
)
WHERE account_id = 1234 AND city = 'Chicago'
虽然看起来很糟糕,但它的性能要高得多。所有条件都可以应用于更大的users
表,但只有不变的条件可以应用于users_changes
表。即用户可以更改城市,但用户不能更改帐户。联合后所有条件的第二次运行是捕获 user_changes
引入的任何更改。
这写起来很麻烦,当查询变得复杂并且涉及到查询构建器时更是如此。因此,我正在寻找方法来说服 sql 规划器跳过我的 user_changes
表上某些谓词的谓词下推,而无需像这样格式化查询。最好有风景。
伪 SQL。伪 SQL。伪 SQL
在我最疯狂的梦想中,我可以告诉查询规划器在哪里可以使用分区谓词,以及在哪里可以使用非分区谓词。
CREATE OR REPLACE VIEW users_view AS (
SELECT * FROM (
SELECT * FROM users
%PARTITION_PREDICATES%
%NON_PARTITION_PREDICATES%
UNION ALL
SELECT * FROM user_changes
%PARTITION_PREDICATES%
QUALIFY ROW_NUMBER() OVER(
PARTITION BY id
ORDER BY last_updated_at DESC
) = 1
)
%PARTITION_PREDICATES%
%NON_PARTITION_PREDICATES%
)
SELECT * FROM users_view
WHERE account_id = 1234 AND city = 'Chicago'
有什么疯狂的想法吗?
【问题讨论】:
您是否正在使用已经硬编码的谓词创建视图?如果我的问题正确,您想简化查询构建,以便仅在查询结束时应用谓词(仍在视图内)? 理想情况下,我希望将视图视为一个知道如何将正确谓词应用于每个表的黑盒。我想将完整的谓词应用于我的users
表,但要手动选择要应用于user_changes
表的谓词。所以是的——这将是为了简化查询构建过程。
【参考方案1】:
您可以添加额外的列 src
来确定源表并在 CASE 中包装谓词:
select * from
(
SELECT u.*, 'users' as src FROM users u
union all
SELECT uc.*, 'users_changes' as src FROM users_changes uc
)
WHERE --applied only to users
case when src = 'users'
then city = 'Chicago' --predicate wrapped in case
else true
end
--applied to all
AND account=12345
【讨论】:
非常酷的主意!谢谢! @micah 您可以使用 AND 或 OR 将所有谓词包装在单个 CASE 中:then city = 'Chicago' AND one_more_condition AND some_other_condition
以上是关于选择性谓词下推查看的主要内容,如果未能解决你的问题,请参考以下文章