我在 Snowflake 数据库中有一个视图定义,其中涉及带有一些连接条件的子查询。当我从视图中选择数据并将某些过滤器应用于主查询时,过滤器似乎不适用于子查询。因此,子查询中的所有分区都会被扫描,而不是仅扫描那些应应用过滤条件的分区。如何修改视图定义以确保过滤器正确应用于子查询并且仅提取相关数据? 简化查询:
CREATE OR REPLACE VIEW my_view AS (
SELECT
main_table.id,
main_table.name,
main_table.date,
main_table.hour,
subquery_table.additional_info
FROM main_table
LEFT JOIN (
SELECT
sub_id,
date,
hour,
additional_info
FROM subquery_table
) subquery_table
ON main_table.id = subquery_table.sub_id
);
从视图中选择数据时,例如
SELECT * FROM my_view
WHERE date = '2023-07-27'
and hour = 0
我注意到所有分区都是从子查询中扫描的,但我希望过滤也适用于那里。
有任何建议欢迎提出,谢谢!
如果您的视图足够复杂和/或您对视图的 SQL 很复杂,或者两者兼而有之,或者月相,则不会发生“下推”过滤器。我们已经经历过这个问题很多年了,我们解决这个问题的方法是使用SQL UDTF将过滤器“传递到视图中”,这样它们总是“下推”。
鉴于我们控制了所有访问层 SQL 生成,我们更改了 SQL 生成层以使用视图上的函数。
select <complexity>
from view_name
<more complexity>
前往:
select <complexity>
from table(udtf_name(filter_parameter_to_push_down))
<more complexity>
这效果非常好。
所以对于你的函数来说它看起来像:
CREATE FUNCTION udtf_my_view(date_filter date, time_filer time)
RETURNS TABLE(id number, name text, date timestamp, hour time, additional_info variant)
AS
$$
SELECT
a.id,
a.name,
a.date,
a.hour,
b.additional_info
FROM main_table as a
LEFT JOIN (
SELECT
c.sub_id,
c.date,
c.hour,
c.additional_info
FROM subquery_table as a
WHERE c.date = date_filter
and c.hour = time_filer
) as b
ON a.id = b.sub_id
);
SELECT * FROM table(udtf_my_view('2023-07-27'::date, 0)
不,这将对
main_table
进行完整扫描,因为您没有对此进行过滤,但 subquery_table
将受到正确限制。假设这是要解决的问题。
还允许强制我们的多帐篷客户数据使用一个函数(即模式版本对齐)而不是每个客户的视图,从而消除了在面向客户的模式更改时替换/创建数百万个视图的需要。