流 + 任务缺少插入?

时间:2021-05-13 22:48:37

标签: snowflake-cloud-data-platform

我们在一个表上设置了一个流,该流通过雪管持续加载。

我们使用每分钟运行一次的任务来使用这些数据,然后我们合并到另一个表中。存在重复键的可能性,因此我们使用 ROW_NUMBER() 窗口函数,按文件创建的时间戳降序排序,其中 row_num=1。这样我们总能得到最新的插入

最初我们使用带有合并语句的标准任务,但我们注意到在某些情况下,由于 snowpipe 不保证按文件暂存的顺序加载,我们使用旧数据更新行。因此,在 WHEN MATCHED 部分,我们添加了一个条件,因此仅当文件创建 ts > existing 时才更新行

但是,由于我们这样做了,对帐检查显示缺少一些新插入。我不确定为什么更改匹配的子句会干扰不匹配的子句。

我的理论是,额外的子句为任务运行增加了一些时间,其中一些运行被跳过,或者下一次运行几乎在最后一次完成后立即发生。这个想法是丢失的行被赶上了中间,偏移量在它们被消耗之前发生了变化

因此,我们将任务更改为调用使用显式事务的存储过程。我们这样做是因为文档似乎暗示使用事务会锁定流。然而,即使这样,我们仍然可以看到新的插入物仍然丢失。我们谈论的是非常小的数字,例如十万分之八

有什么想法可能会发生什么吗?

下面的示例任务代码(不是 sp 版本)

WAREHOUSE = TASK_WH
SCHEDULE = '1 minute'
WHEN SYSTEM$stream_has_data('my_stream')
AS
MERGE INTO processed_data pd USING (
  select 
  ms.*, 
  CASE WHEN ms.status IS NULL THEN 1/mv.count ELSE NULL END as pending_count, 
  CASE WHEN ms.status='COMPLETE' THEN 1/mv.count ELSE NULL END as completed_count
  from my_stream ms
  JOIN my_view mv ON mv.id = ms.id
  qualify
    row_number() over (
      partition by 
        id
      order by
        file_created DESC
    ) = 1
) ms ON ms.id = pd.id
    WHEN NOT MATCHED THEN INSERT (col1, col2, col3,...  )
                          VALUES (ms.col1, ms.col2, ms.col3,...)    
WHEN MATCHED AND ms.file_created >= pd.file_created THEN UPDATE SET pd.col1 = ms.col1, pd.col2 = ms.col2, pd.col3 = ms.col3, ....
;

2 个答案:

答案 0 :(得分:0)

我不完全确定这里出了什么问题,但 Snowflake 某处给出了与文件创建时间相关的建议。它表明文件创建的时间戳是在云服务中计算的,它可能与您想象的有点不同。还有另一个与雪管和数据摄取相关的建议。队列服务需要一分钟来消耗来自管道的数据,如果您在一分钟内有大量数据在内部传输,您可能最终会遇到此问题。看看你的实现并模拟以 1 分钟为间隔推送数据是否解决了该问题并且不依赖于文件创建时间。

答案 1 :(得分:0)

条件 "AND ms.file_created >= pd.file_created" 似乎是作为一种机制添加的,以避免多次更新同一行。

替代方法可能是使用 IS DISTINCT FROM 将源列与目标列进行比较(id 除外):

MERGE INTO processed_data pd USING (
  select 
  ms.*, 
  CASE WHEN ms.status IS NULL THEN 1/mv.count ELSE NULL END as pending_count, 
  CASE WHEN ms.status='COMPLETE' THEN 1/mv.count ELSE NULL END as completed_count
  from my_stream ms
  JOIN my_view mv ON mv.id = ms.id
  qualify
    row_number() over (
      partition by 
        id
      order by
        file_created DESC
    ) = 1
) ms ON ms.id = pd.id
    WHEN NOT MATCHED THEN INSERT (col1, col2, col3,...  )
                          VALUES (ms.col1, ms.col2, ms.col3,...)    
WHEN MATCHED 
 AND (pd.col1, pd.col2,..., pd.coln) IS DISTINCT FROM (ms.col1, ms.col2,..., ms.coln)
THEN UPDATE SET pd.col1 = ms.col1, pd.col2 = ms.col2, pd.col3 = ms.col3, ....;

这种方法还可以防止在没有任何变化时更新行。