有人可以向我解释为什么第一个查询性能良好(仅处理 254KB),而后两个查询则处理 750MB?这些查询之间的唯一区别在于,第一个查询包含硬编码的 ID 列表,第二个查询从表中获取完全相同的 ID 列表(无硬编码),第三个查询从硬编码数组中获取其 ID 列表。
src_id
字段在所有表中的分区相同。
demo_table
包含 270 万条记录,均匀分布在 10,000 个分区中。
id_table
仅包含1个字段和3条记录。
-- this query performs well - only processes 254KB of data.
select *
from `myproject.mydataset.demo_table`
where src_id in ( 1435718211154057483
, 1260912821261010025
, 3916818671952292004)
;
-- this query performs poorly - processes 750 of data.
-- the subquery returns only 3 rows, the exact same ids as used above.
select *
from `myproject.mydataset.demo_table`
where src_id in (select src_id from myproject.mydataset.id_table)
;
-- this query performs poorly - processes 750 of data.
-- This query example is included only to demonstrate that the performance
-- degradation seems to related to the presence of a subquery.
select *
from `myproject.mydataset.demo_table`
where src_id in (select src_id
from unnest((
select [ 1435718211154057483
, 1260912821261010025
, 3916818671952292004])) as src_id)
看起来 BigQuery 执行查询的方式有所不同,具体取决于
IN
子句是否包含子查询或简单的值列表。
我真正想要完成的是让第二个查询和第一个查询一样工作(没有硬编码)。 谁能向我解释如何构造这个查询以获得更好的性能?
根据文档:
要限制查询中扫描的分区,请在过滤器中使用常量表达式。如果您在查询过滤器中使用动态表达式,BigQuery 必须扫描所有分区。
您的第一个查询使用常量表达式,即值列表。 您的其他示例不使用常量表达式,它们使用子查询。