无法在没有可用于分区消除的过滤器的情况下查询表

Posted

技术标签:

【中文标题】无法在没有可用于分区消除的过滤器的情况下查询表【英文标题】:Cannot query over table without a filter that can be used for partition elimination 【发布时间】:2018-07-05 14:39:22 【问题描述】:

我有一个分区表,很想使用 MERGE 语句,但由于某种原因不起作用。

MERGE `wr_live.p_email_event`  t
using `wr_live.email_event` s
on t.user_id=s.user_id and t.event=s.event and t.timestamp=s.timestamp
WHEN NOT MATCHED THEN
INSERT (user_id,event,engagement_score,dest_email_domain,timestamp,tags,meta)
values (user_id,event,engagement_score,dest_email_domain,timestamp,tags,meta)

我明白了

如果没有过滤器,则无法查询表 'wr_live.p_email_event' 可用于分区消除。

正确的语法是什么?还有一种方法可以表达更短的插入内容吗?不命名所有列?

【问题讨论】:

【参考方案1】:

正确的语法是什么?

您可以从错误消息中看到 - 您的分区 wr_live.p_email_event 表是在 require partition filter 设置为 true 的情况下创建的。这意味着对该表的任何查询都必须在相应的分区字段上具有一些过滤器

假设 timestamp 是分区字段 - 您可以执行以下操作

MERGE `wr_live.p_email_event`  t
USING `wr_live.email_event` s
ON t.user_id=s.user_id AND t.event=s.event AND t.timestamp=s.timestamp
AND DATE(t.timestamp) > CURRENT_DATE()  -- this is the filter you should tune 
WHEN NOT MATCHED THEN
INSERT (user_id,event,engagement_score,dest_email_domain,timestamp,tags,meta)
VALUES (user_id,event,engagement_score,dest_email_domain,timestamp,tags,meta)   

所以你需要做下面的行,这样它实际上不会过滤掉你需要参与的任何内容

AND DATE(t.timestamp) <> CURRENT_DATE()  -- this is the filter you should tune 

例如,我发现,将其设置为将来的时间戳 - 在许多情况下可以解决问题,例如

AND DATE(t.timestamp) > DATE_ADD(CURRENT_DATE(), INTERVAL 1 DAY)   

当然,如果您的wr_live.email_event 表也分区,require partition filter 设置为 true - 您需要为 s.timestamp 添加相同的过滤器

还有什么方法可以表达更短的插入内容?没有命名所有列?

BigQuery DML 的 INSERT 需要 column names to be specified - 没有办法(至少我知道)使用 INSERT 语句来避免它 同时,您可以通过从查询结果中使用 DDL 的 CREATE TABLE 来避免这种情况。这不需要列出列

例如,如下所示

CREATE OR REPLACE TABLE `wr_live.p_email_event`
PARTITION BY DATE(timestamp) AS
SELECT * FROM `wr_live.p_email_event` 
WHERE DATE(timestamp) <> DATE_ADD(CURRENT_DATE(), INTERVAL 1 DAY)
UNION ALL 
SELECT * FROM `wr_live.email_event` s
WHERE NOT EXISTS (
  SELECT 1 FROM `wr_live.p_email_event` t
  WHERE t.user_id=s.user_id AND t.event=s.event AND t.timestamp=s.timestamp
  AND DATE(t.timestamp) > DATE_ADD(CURRENT_DATE(), INTERVAL 1 DAY)
)

您可能还想通过 OPTIONS() 包含表格选项列表 - 但看起来尚不支持过滤器属性 - 因此,如果您确实拥有/需要它 - 上面将“删除”此属性:o(

【讨论】:

感谢您的提醒——我认为将 require_partition_filter 与 CREATE TABLE 一起使用应该可以,但我们需要记录它。 太棒了。谢谢@ElliottBrossard

以上是关于无法在没有可用于分区消除的过滤器的情况下查询表的主要内容,如果未能解决你的问题,请参考以下文章

$eq 内部过滤器不适用于数组字段 - Mongodb

filter这样的运算符可用于消除噪音。

在 oracle sql 12c 中可以绕过分区吗?

MySQL分区表

KendoUI 下拉过滤器不适用于 AngularJS

在弹性搜索中不过滤的情况下提升匹配术语查询的结果