代码之家  ›  专栏  ›  技术社区  ›  Joe

为什么这两个查询之间的性能存在如此大的差异?

  •  0
  • Joe  · 技术社区  · 1 年前

    有人能解释一下为什么第一个查询执行良好(仅处理254KB),而第二个查询处理750MB吗?这些查询之间的唯一区别是,第一个查询包含一个硬编码的ID列表,第二个查询从表中获取完全相同的ID列表(没有硬编码),第三个查询从硬编码数组中获取其ID列表。

    这个 src_id 字段在所有表中都被相同地分区。

    这个 demo_table 包含270万条记录,均匀分布在10000个分区上。

    这个 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 子句包含一个子查询或一个简单的值列表。

    我真正想做的是让第二个查询和第一个查询一样工作(没有硬编码)。有人能向我解释一下如何构造这个查询以获得更好的性能吗?

    1 回复  |  直到 1 年前
        1
  •  1
  •   rtenha    1 年前

    根据 documentation :

    要限制查询中扫描的分区,请在筛选器中使用常量表达式。如果在查询筛选器中使用动态表达式,BigQuery必须扫描所有分区。

    您的第一个查询使用常量表达式(值列表)。您的其他示例不使用常量表达式,而是使用子查询。