选择性谓词下推查看
Selective Predicate Pushdown To View
我有一个经常更新的大型列存储 table。我不会将更新直接提取到源 table 中,因为在大多数情况下,这会导致少量更新导致完整的 table 微分区重建。相反,我将更新流式传输到更新 table,并在查询时将两者结合起来。在实践中效果很好。
所以简化事情,我将把它放在一个视图中 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
table 和 user_changes
table 具有相同的方案以及一些分区配置。这样我就可以在视图上使用谓词下推,仅对正确分区内的 select 用户。假设这是 account_id
.
SELECT * FROM users_view
WHERE account_id = 1234
但是 users
table 比 user_changes
table 大很多,我想将更多谓词下推到 users
table 而不将额外的谓词下推到 user_changes
table。为什么?因为 users
table 上的匹配虽然准确率为 98%,但 positives/negatives 是错误的。需要来自 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
table,但只有不变的条件才能应用于 users_changes
table。即用户可以更改城市,但用户不能更改帐户。联合后所有条件的第二个 运行 是捕获 user_changes
引入的任何更改。
这写起来很麻烦,而且随着查询变得复杂和查询构建器的参与,更是如此。所以我正在寻找说服 sql 计划者跳过我的 user_changes
table 上某些谓词的谓词下推的方法,而无需像这样格式化查询。最好有风景。
PSUEDOSQL。伪装 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'
有什么疯狂的想法吗?
您可以添加额外的列 src
以确定来源 table 并在 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
我有一个经常更新的大型列存储 table。我不会将更新直接提取到源 table 中,因为在大多数情况下,这会导致少量更新导致完整的 table 微分区重建。相反,我将更新流式传输到更新 table,并在查询时将两者结合起来。在实践中效果很好。
所以简化事情,我将把它放在一个视图中 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
table 和 user_changes
table 具有相同的方案以及一些分区配置。这样我就可以在视图上使用谓词下推,仅对正确分区内的 select 用户。假设这是 account_id
.
SELECT * FROM users_view
WHERE account_id = 1234
但是 users
table 比 user_changes
table 大很多,我想将更多谓词下推到 users
table 而不将额外的谓词下推到 user_changes
table。为什么?因为 users
table 上的匹配虽然准确率为 98%,但 positives/negatives 是错误的。需要来自 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
table,但只有不变的条件才能应用于 users_changes
table。即用户可以更改城市,但用户不能更改帐户。联合后所有条件的第二个 运行 是捕获 user_changes
引入的任何更改。
这写起来很麻烦,而且随着查询变得复杂和查询构建器的参与,更是如此。所以我正在寻找说服 sql 计划者跳过我的 user_changes
table 上某些谓词的谓词下推的方法,而无需像这样格式化查询。最好有风景。
PSUEDOSQL。伪装 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'
有什么疯狂的想法吗?
您可以添加额外的列 src
以确定来源 table 并在 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