google cloud spanner upsert 仅支持主键

问题描述 投票:0回答:1

希望您度过愉快的假期。

我正在尝试将一些upsert代码片段从mysql迁移到spanner中,但不知何故spanner只支持主键上的upsert,而不支持唯一键作为辅助索引。

mysql 示例:

CREATE TABLE persons (
    id int PRIMARY KEY,
    name varchar(45),
    ssn varchar(15),
    CONSTRAINT uc_ssn Unique(ssn)
);


INSERT INTO table (id,name,ssn)
VALUES (1,'a', '111-111-1111')
ON DUPLICATE KEY
    UPDATE name=name;

# below insert should update name into 'b' due to uc_ssn constraint and on duplicate key update.
INSERT INTO table (id,name,ssn)
VALUES (2,'b', '111-111-1111')
ON DUPLICATE KEY
    UPDATE name=name;

但是在spanner中,使用

Mutation.newInsertOrUpdateBuilder
进行类似的更改会报告唯一的密钥违规。 谷歌支持指出 upsert 只能使用主键进行重复检查。 由于 id 不同,spanner 将其作为新记录,因此由于辅助键的唯一键约束而无法插入它。

我们的代码当前运行在mysql上,它支持具有唯一约束的重复键更新。 由于 Spanner 不支持相同的功能,我看到了 2 个选项:

  1. 从 sha256 创建 id(辅助唯一键中的列),然后使用 id(主键)进行更新插入。
  2. 读一致事务内:查询是否存在具有唯一键的记录,如果存在则使用update,否则尝试insert。 我觉得选项1更简单,有什么问题吗? sha256 有 2^256 个可能的值,因此碰撞的改变应该是极不可能的。 对于简单的更新插入,选项 2 似乎有点复杂,我想知道它可能运行得更慢。

非常感谢任何建议。

感谢与问候

google-cloud-spanner
1个回答
0
投票
  1. 从唯一约束值生成主键:这肯定是最快、最简单的解决方案。理论上有可能发生按键碰撞,但这只是理论上的问题,而不是实际问题。因此,仅根据这个问题中的信息,我会选择这个。
  2. 首先执行
    SELECT
    检查记录是否存在会比替代方案 1 慢得多。

替代方案

您是否考虑过将

ssn
作为主键?我知道这意味着您正在创建一个包含有意义值的主键。但如果您选择从
ssn
生成主键,那么您已经部分地这样做了。

我认为

ssn
作为主键的一个重要原因是如果您要从任何其他表引用
person
表。这意味着您的数据库中会有
ssn
值分布在不同的表中,而您可能不希望这样。

© www.soinside.com 2019 - 2024. All rights reserved.