获取插入到雪花数据仓库中的行的标识

Posted

技术标签:

【中文标题】获取插入到雪花数据仓库中的行的标识【英文标题】:Get identity of row inserted in Snowflake Datawarehouse 【发布时间】:2019-05-19 03:52:33 【问题描述】:

如果我有一个带有自动递增 ID 列的表,我希望能够在该表中插入一行,并获取我刚刚创建的行的 ID。我知道一般来说,*** 问题需要某种尝试或研究工作的代码,但我不确定从 Snowflake 开始的地方。我已经挖掘了他们的documentation,但我一无所获。

到目前为止,我能做的最好的事情是尝试result_scan()last_query_id(),但这些并没有给我任何有关插入行的相关信息,只是确认插入了一行。

我相信我要求的是 MS SQL Server 的 SCOPE_IDENTITY() 函数。

MS SQL Server 的SCOPE_IDENTITY() 是否有 Snowflake 等效函数?

编辑:为了在这里有代码:

CREATE TABLE my_db..my_table
(
    ROWID INT IDENTITY(1,1),
    some_number INT,
    a_time TIMESTAMP_LTZ(9),
    b_time TIMESTAMP_LTZ(9),
    more_data VARCHAR(10)
);
INSERT INTO my_db..my_table
(
    some_number,
    a_time,
    more_data
)
VALUES
(1, my_time_value, some_data);

我想为我刚刚插入的这一行获得自动增量ROWID

【问题讨论】:

原谅我的无知...你不只是想要 MAX(ROWID) 吗?所以... SELECT MAX(ROWID) FROM my_db.my_table; @JonJaussi 假设有 5-20 个其他进程同时将记录插入到该表中。 MAX(ROWID) 可能会抓取由另一个进程在同一时间段内创建的行。 感谢您的澄清。您的数据中是否存在“自然键”?您插入的记录中的其他字段的某些串联组合会将记录定义为唯一?这个想法是您可以使用“自然键”查找 ROWID(例如:some_number | a_time | more_data)? @JonJaussi 我现在正在为此做一些事情,但我觉得这样做很草率。我真的希望有一个更合适的方法来获得ROWID 【参考方案1】:

注意:在极少数情况下,以下答案可能不是 100% 正确,请参阅下面的更新部分

原答案

Snowflake 今天不提供SCOPE_IDENTITY 的等效项。

但是,您可以利用 Snowflake 的 time travel 在执行给定语句后立即检索列的最大值。

这是一个例子:

create or replace table x(rid int identity, num int);
insert into x(num) values(7);
insert into x(num) values(9);
-- you can insert rows in a separate transaction now to test it
select max(rid) from x AT(statement=>last_query_id());
----------+
 MAX(RID) |
----------+
 2        |
----------+

如果您想稍后访问它,也可以将last_query_id() 保存到变量中,例如

insert into x(num) values(5);
set qid = last_query_id();
...
select max(rid) from x AT(statement=>$qid);

注意 - 它通常是正确的,但如果用户例如手动将较大的值插入rid,可能会影响此查询的结果。

更新

注意,我意识到上面的代码很少会产生错误的答案。

由于像Snowflake这样的分布式系统中查询的各个阶段的执行顺序可能是不确定的,并且Snowflake允许并发INSERT语句,因此可能会发生以下情况

两个查询,Q1Q2,做一个简单的单行 INSERT,大致同时开始 Q1 开始,有点超前 Q2 开始 Q1IDENTITY 列创建一个值为1 的行 Q2IDENTITY 列创建一个值为2 的行 Q2 领先于 Q1 - 这是关键部分 Q2 提交,在时间 T2 标记为已完成 Q1 提交,在时间 T1 标记为已完成

请注意,T1 晚于 T2。现在,当我们尝试执行SELECT ... AT(statement=>Q1) 时,我们将看到T1 的状态,包括之前语句的所有更改,因此包括来自Q2 的值2。这不是我们想要的。

解决方法可能是将unique identifier 添加到每个INSERT(例如,来自单独的SEQUENCE 对象),然后使用MAX

对不起。分布式事务很难:)

【讨论】:

这看起来很有希望。我会尽快尝试并报告! 对不起,我意识到我的答案可能会产生错误的结果,更新它。 @MarcinZukowski Snowflake 正在解决这个问题吗?我的任务是为我们公司调查 Snowflake,目前我看到的唯一一个引人注目的是这个问题。从雪花社区论坛看来,没有取得任何进展。任何颜色都将不胜感激。 @JohnZabroski 它在我们的待办事项清单上,但目前还没有积极的开发。如果这阻碍了您,请通过您的销售/支持渠道提出,这可能有助于确定优先级。 在使用了一年多之后才报告——@MarcinZukowski 的更新是正确的,我们遇到了这种方法的并发问题。话虽如此,我还没有时间在每个INSERT 中使用unique identifier 更新实现此功能的功能。公平地说,在我的用例中,它支持网站的一些后端功能,而这并不是数据仓库一开始就存在的目的。

以上是关于获取插入到雪花数据仓库中的行的标识的主要内容,如果未能解决你的问题,请参考以下文章

由于未选择活动仓库,对雪花数据库的查询不起作用

如何找到雪花中的总连接数

数据仓库建模之雪花模型和星形模型

数据仓库中的几种模型

数据仓库建模技巧

跨区域的雪花复制:增加任一端的仓库大小会影响速度吗?