如何在 vertica 中获取最后发布的序列 ID?

Posted

技术标签:

【中文标题】如何在 vertica 中获取最后发布的序列 ID?【英文标题】:How can I get the last issued sequence ID in vertica? 【发布时间】:2018-07-30 15:10:13 【问题描述】:

背景:我正在从 postgreSQL 迁移到 Vertica,发现 IDENTITYAUTO_INCREMENT 列中存在一些问题。其中一个问题是,vertica 无法将值分配给IDENTITY 列或更改已将数据放入IDENTITY 列的列。因此,我创建了一个序列并将列的默认值设置为唯一的:

SELECT MAX(id_column) FROM MY_SCHEMA.my_table; 

这是 12345

CREATE SEQUENCE MY_SCHEMA.seq_id_column MINVALUE 12346 CACHE 1; 

ALTER TABLE MY_SCHEMA.my_table 
ALTER COLUMN id_column SET DEFAULT(MY_SCHEMA.seq_id_column.nextval);

ALTER TABLE MY_SCHEMA.log ADD UNIQUE(id_column);

按预期工作。在这种情况下,我已停用缓存,因为我在单节点安装上,并且我希望我的 ID 列是连续的。但是,这不是集群安装的选项,因为所需的锁会导致瓶颈。

问题:在具有多个节点的 vertica 集群中,如何访问会话中最后插入的 ID(无需额外选择)?

例如在 postgreSQL 中我可以做类似的事情

INSERT INTO MY_SCHEMA.my_table RETURNING id_column;

这在 Vertica 中不起作用。此外,Vertica 的LAST_INSERT_ID() 函数不适用于命名序列。我也觉得,查询MY_SCHEMA.seq_id_columncurrent_value 可能会由于缓存而给出错误的结果,但我对此不确定。

为什么没有额外的 SELECT?

据我所知,选择只会在提交后给出正确的值。由于性能问题,我无法在每次插入后进行提交。

【问题讨论】:

你检查系统表SEQUENCES了吗?另外,请您描述一下您通过获取最后一个插入 id 来实现的目标吗? 如前所述,SEQUENCES 不支持 LAST_INSERT_ID,我担心在查询 SEQUENCES 表时会遇到竞争条件。我只想拥有会话中最后插入条目的主键。 我想知道 CURRVAL 是否适用于此? F.e. CURRVAL(MY_SCHEMA.seq_id_column)。 Reference。啊没关系,你担心缓存的效果。 走开 @LukStorms 实际上,确实如此。我用两个并发会话尝试了这个,每个会话都给了我正确的(缓存的)值。如果您将评论添加为答案,您将获得赏金。 谢谢,虽然很诱人,但我还是会转告的。会感觉不对。我所做的只是根据以前使用其他分布式 DBMS 的经验查找一些文档。我无法访问 Vertica。而且我不喜欢发布一个我无法测试自己的答案,或者不知道它会不会用心。既然您已经通过测试完成了繁重的工作,并且没有其他人提出一个体面的答案,那么这些点也可能会退还给您。也许您甚至可以发布自己的答案。因为这个问题本身可能对有一天会遇到同样问题的其他人有用。 【参考方案1】:

LukStorms 的 cmets 为我指明了正确的方向。

NEXTVAL() 函数(据我测试)在单个会话查询它们的情况下提供连续值。此外,在并发访问中,如果在插入之后发出,CURRVAL 会检索缓存的值,该值保证是唯一的,但不一定是连续的。因为我从来没有像在默认子句中那样在其他任何地方调用NEXTVAL,所以这解决了我的问题,尽管可能存在插入之间对NEXTVAL 的额外调用会增加序列计数器的情况。

我能想到的一种情况(我将在未来进行测试)是如果 AUTO COMMIT 设置为 OFF(对于 vertica 客户端驱动程序默认为 ON)会发生什么。

更新:

这甚至似乎适用于AUTOCOMMIT 作为OFF(使用vertica-python 客户端驱动程序显示,其中C 是连接,cur 是光标):

cur.execute("SELECT NEXTVAL('my_schema.my_sequence');")
cur.fetchall()
--> 1
cur.execute("SELECT CURRVAL('my_schema.my_sequence');")
cur.fetchall()
--> 1
cur.execute("SET SESSION AUTOCOMMIT TO OFF")
cur.execute("SELECT NEXTVAL('my_schema.my_sequence');")
cur.execute("SELECT NEXTVAL('my_schema.my_sequence');")
cur.execute("SELECT NEXTVAL('my_schema.my_sequence');")
cur.execute("SELECT CURRVAL('my_schema.my_sequence');")
cur.fetchall()
--> 4

但是,这似乎在连接回滚期间没有改变。所以会发生以下情况:

C.rollback()
cur.execute("SELECT CURRVAL('my_schema.my_sequence');")
cur.fetchall()
--> 4

【讨论】:

有趣。我有点期待这样的事情,序列值不会被回滚。我猜你的目标是连续数字。但也许你可以在交易前保留价值。或者从表中获取 MAX 值。并在回滚后使用 RESTART 更改序列?参考here 据我所知,由于全局锁,连续数字会导致瓶颈。我愿意牺牲连续性来换取性能。

以上是关于如何在 vertica 中获取最后发布的序列 ID?的主要内容,如果未能解决你的问题,请参考以下文章

Vertica:将字符串拆分为数组并将其分组以获取一组唯一值?

如何在 Keras 中同时获取 LSTM 或 GRU 的最后输出和完整序列?

Vertica SQL 用于按列获取数据

如何在 Delphi 中获取主板 ID 或序列号?

如何使用 Apache Apex 将数据从 DB2 批量摄取到 Vertica

使用 Hue sqoop 2 从 vertica 获取数据