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

数据库分库分表之后,所有表在一起,两个字段怎么做组合唯一索引?

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

    当时我答的是单独新建一个表,做组合索引,写入成功就插入,没写入成功就失败。

    23 条回复    2023-06-19 00:21:43 +08:00
    encro
        1
    encro  
       316 天前   ❤️ 1
    为难你了,
    初级程序员面试架构师题目。。。

    一般来说,不了解何时该分库分表的人,不配了解这个问题,这个问题只是为了让你早点知难而退。
    gof817
        2
    gof817  
       316 天前   ❤️ 1
    这种最简单的就是用其他的 kv 库
    LeegoYih
        3
    LeegoYih  
       316 天前   ❤️ 1
    定义 2 个字段组合的路由规则
    dode
        4
    dode  
       316 天前 via Android
    pg 的分区表有并行查询,可以在整个表上加约束
    unregister
        5
    unregister  
    OP
       316 天前
    @encro 第一次我说使用分布式锁,第二次我说用中间表。大佬您有什么好的方案吗
    realpg
        6
    realpg  
       316 天前   ❤️ 3
    分库分表规则中,涉及唯一性约束的字段的同值就不应该分到不同的表里面去

    如果架构师只会按时间分表,那这公司不待也罢
    draymonder
        7
    draymonder  
       316 天前   ❤️ 2
    假设两个字段是 (user_id ,user_type)

    1. 方案一,将两个字段映射到一个 v_user_id 上,对 v_user_id 进行分库分表。
    v_user_id -> (user_id ,user_type) 的数据用一个 mysql 表存下来,( user_id ,user_type )-> v_user_id 通过 kv 数据库存储,这样双向映射都有了
    2. 方案二,对 user_id 进行分库分表,所有写入和查询操作都带上 user_type

    保证唯一不一定非要唯一索引,也可以通过事务来保证
    Azure99
        8
    Azure99  
       316 天前
    有没有可能,有种分表策略叫哈希分表?
    encro
        9
    encro  
       316 天前
    @unregister

    通常这个问题就是一个坑,我不知道原始问题是什么,所以没法估计这个出题的用意。

    如果你是普通的分表,那么这个和你分表的 key 有关系,

    如果是现成方案也是和分区 key 有关联。

    先问清楚方案才能给解决方案。
    IDAEngine
        10
    IDAEngine  
       316 天前
    水平拆分还是垂直拆分,看具体问题。
    echo1937
        11
    echo1937  
       316 天前   ❤️ 1
    分表好办,

    不支持全局索引的数据库,本地索引只支持分区内的唯一性,无法支持表上的唯一性,因此如果要用本地索引去给表做唯一性约束,则约束中必须要包括分区键列。

    支持全局索引的数据库比如 Oracle ,没有这种限制,只是要接受全局索引比本地索引可用性低的现实。

    分库麻烦一些,
    如果是分布式数据库,基本上无需使用者担心,只要这个数据库实现了主键的唯一性约束,

    如果是非分布式数据库,办法也是有的,比如结合 kv 库啊,用事务去解决啊,只是带来的代价未必小。
    Ericcccccccc
        12
    Ericcccccccc  
       316 天前
    分库分表的核心就在于你得自定义分表规则, 比如一个地区的用户在一张表里, 天然和其它地区的表是不冲突的.
    bctdg
        13
    bctdg  
       316 天前   ❤️ 1
    根据这两个 key 来做 partition 就好了吧?如果没有其他要求的话,这样是最简单的。这样做的问题可能是不同的分表数据量不均匀。
    opengps
        14
    opengps  
       316 天前 via Android
    分库分表之后为什么会在一起?分裤分表本身就应该有个拆分逻辑作为前提,你这连基础的前提都没写出来
    yueye115
        15
    yueye115  
       316 天前
    @draymonder 我的想法是,把 user_id 和,user_type 进行字符串拼接,然后用 26 进制或者取字符串的字节等方法,把字符串转成一个数字,用这个数字进行分表可行否
    yueye115
        16
    yueye115  
       316 天前
    @draymonder 忘了说了,每个子表该字段加唯一索引
    yueye115
        17
    yueye115  
       316 天前
    @draymonder 不对啊,如果按照 user_id 进行分表,那直接在子表加 user_id 和 user_type 的联合唯一所以也能确保不重复。我感觉我理解错了
    season8
        18
    season8  
       316 天前
    我对着标题看了好半天才理解问题是啥:

    是指有两个字段组合具有唯一性,分表后,如何保证分表之间的唯一性?

    hash 分表,无论几个字段,都可以用 hash ,只需要解决数据倾斜问题。
    yueye115
        19
    yueye115  
       316 天前   ❤️ 1
    如果把这个问题升级下,在以 id 进行分库的基础上,改造旧表,加个 user_id 和 user_type 的唯一验索引应该怎么搞
    draymonder
        20
    draymonder  
       316 天前
    @yueye115
    1. ( user_id ,user_type )-> v_user_id 本质上是个 hash 的过程,我理解满足 `唯一映射` 就行,v_user_id 可以通过 id 生成器生成,也可以用字符串拼接而成
    2. 表迁移大多有成熟的方法
    2.1 扫存量的数据+通过 binlog 迁移,找个低峰时间,全量切到新的分库分表中
    2.2 代码做兼容,通过时间点 /id 大小,小于相应的时间点 /id 大小的,走老表,否则走新表
    xuanbg
        21
    xuanbg  
       315 天前
    @realpg 大概率是有点分表需求,然后无脑使用某些分表中间件,自己对分表根本没有概念。。。要我说,对分表有概念的,根本用不上那些分表中间件。如果说分表会影响业务逻辑,那这个分表肯定就分错了。
    xuanbg
        22
    xuanbg  
       315 天前   ❤️ 1
    推荐一个解决方案,就是利用 redis 的 setIfAbsent 方法,这个方法是如果 key 不存在,则 set k/v ,然后返回 true 。也就是说,返回 true 的话,就表明 key 是唯一。
    LuckyLight
        23
    LuckyLight  
       315 天前
    这两个字段有没有哪个字段是分表键?如果有,直接在分表里用这两个字段创建 unique key 。如果没有,简单的方式就是创建一个中间表,这两个字段创建 unique key ,除了这两个字段,再加上分表键和分表的主键,方便后续查询。
    当然,更简单粗暴的就是上分布式数据库,比如 TiDB😂。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1633 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 16:49 · PVG 00:49 · LAX 09:49 · JFK 12:49
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.