V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
wuhunyu
V2EX  ›  程序员

腾讯云 TDSQL PostgreSQL 版 无法创建唯一索引问题

  •  
  •   wuhunyu · 35 天前 · 1019 次点击
    这是一个创建于 35 天前的主题,其中的信息可能已经有所发展或是发生改变。

    问题描述

    假设我的建表语句是

    create table users
    (
        id        bigint primary key,
        user_name varchar(120) not null
    );
    

    现在想要为 user_name 字段新增一个唯一索引。如果是在 postgresql 中,如下 sql 是可以正常执行的

    create unique index uni_user_name on users (user_name);
    

    但在 TDSQL 环境下,这条 sql 执行失败了,报错提示

    ERROR:  Unique index of partitioned table must contain the hash/modulo distribution column.
    

    探索

    TDSQL 是一款腾讯开发的分布式数据库系统,近期公司有打算兼容 TDSQL 。目前使用的数据库是 postgresql 。迁移数据时遇到了一个有关唯一索引的问题

    以下是 TDSQL 官网的资料:

    1. 非 shard key 字段不能建立唯一索引
    2. 不指定 shard key 建表方法,系统默认使用第一个字段作为表的 shard key

    分布键选择原则:

    • 分布键只能选择一个字段。
    • 如果有主键,则选择主键做分布键。
    • 如果主键是复合字段组合,则选择字段值选择性多的字段做分布键。
    • 也可以把复合字段拼接成一个新的字段来做分布键。
    • 没有主键的可以使用 UUID 来做分布键。
    • 总之一定要让数据尽可能的分布得足够散。

    创建和删除数据表

    创建和删除索引

    尝试解决

    1. 将唯一索引的创建语句修改为包含 shard key
    create table users
    (
        id        bigint primary key,
        user_name varchar(120) not null
    ) distribute by shard(id);
    
    create unique index uni_user_name_id on users (user_name, id);
    

    可以正常执行,但这个组合的唯一索引失去了 user_name 字段唯一的限制

    1. user_name 设置为 shard key
    create table users
    (
        id        bigint,
        user_name varchar(120) not null
    ) distribute by shard(user_name);
    
    create unique index uni_user_name on users (user_name);
    

    这种情况下,如果表有多个唯一索引,也是不行的,因为 shard key 只能是一个字段,更不要说我的业务里面还有组合的唯一索引

    1. 创建一个新表,命名为 uni_users_user_name,将 user_name 作为主键和 shard key 。创建一个触发器,在新增或者修改时,也去修改 uni_users_user_name,通过 uni_users_user_name 来校验 user_name 是否唯一

    这种方案我并没有实践,一方面触发器现在已经很少使用了,使用的话会对现有的业务造成哪些影响也需要评估。另一方面,多个唯一索引需要建立多张表,如果组合唯一索引的话,又应该怎么处理呢?

    create table uni_users_user_name
    (
        user_name varchar(120) primary key,
        id        bigint
    ) distribute by shard(user_name);
    

    我的疑问

    我想这个问题应该在其他分布式数据库中也存在的,但目前好像并没有好的解决方案。我去咨询了官方客服,她们给我的反馈是分布式数据库是有挺多的限制,建议我使用她们的 postgresql

    我想问问各位,有没有较好的方案可以在不改动业务,或者小改动的情况下,解决业务上强依赖数据库唯一索引的问题

    7 条回复    2024-10-24 09:55:42 +08:00
    mark2025
        1
    mark2025  
       35 天前
    普通项目根本用不到分布式数据库,单机 pg 数据库足以。不要自己给自己挖坑
    mark2025
        2
    mark2025  
       35 天前   ❤️ 1
    分布式数据库是不是伪需求?
    https://pigsty.cc/zh/blog/db/distributive-bullshit/
    wuhunyu
        3
    wuhunyu  
    OP
       35 天前
    @mark2025 领导想要适配 TDSQL ,我也清楚现在的系统即便迁移到了分布式数据库,但没有改造 sql ,性能可能会不如单机的 pg
    263
        4
    263  
       35 天前
    其实可以用,TDSQL-C PostgreSQL 版

    https://cloud.tencent.com/product/tdcpg
    wuhunyu
        5
    wuhunyu  
    OP
       35 天前
    @263 领导不买账呐,而且这个数据库的 pg 引擎都买不了
    liuhan907
        6
    liuhan907  
       35 天前
    @wuhunyu
    用 CRDB 就没这个问题(
    bthulu
        7
    bthulu  
       35 天前
    那就不用唯一索引, 程序里控制好唯一性就行了. 你事先跟领导说清楚有风险, 万一出事了, 让领导背锅就好了.
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5434 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 07:59 · PVG 15:59 · LAX 23:59 · JFK 02:59
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.