• 叶明
    2024-10-09 来自江苏
    另外,我看 gh-ost 的实现方式是另外一种,从左右边界和联合主键中字段之间的区间来考虑 1. 最左边的边界: id1='a' and id2='a' and id3='1',可以通过这个查询条件来拿到最左边界的记录 2. 联合主键 (id1, id2, id3) 中 id1 处于索引中第一列,因此 id1 是有序的,查询条件 id1>'a' 拿到除 id1='a' 之外的所有记录 3. 步骤2完成后,只需要考虑 id1='a' 的最后一条记录与第一条记录 (id1='a', id2='a', id3='1') 这段范围的记录了 4. 当 id1='a' and id2='a' 时,要想访问 id3 的所有记录,查询条件得为 id3 > '1',这样就能拿到 id1, id2 为固定值时,id3 > '1' 的所有记录,id3 = 1 的边界值在步骤 1 中已经拿到了 5. 步骤4完成后,满足 id1='a' and id2='a' 条件的所有记录已经能拿到了,接下来,拿 id1 = 'a' 时,id2 > 'a' 的所有记录,这样,id1='a' 的所有记录就都能拿到了 select /* gh-ost `test`.`t_business` iteration:0 */ `id1`, `id2`, `id3` from `test`.`t_business` where ( (`id1` > _binary 'a') or ( ((`id1` = _binary 'a')) AND (`id2` > _binary 'a') ) or ( ( (`id1` = _binary 'a') and (`id2` = _binary 'a') ) AND (`id3` > _binary '1') ) or ( (`id1` = _binary 'a') and (`id2` = _binary 'a') and (`id3` = _binary '1') ) ) and ( (`id1` < _binary 'd') or ( ((`id1` = _binary 'd')) AND (`id2` < _binary 'a') ) or ( ( (`id1` = _binary 'd') and (`id2` = _binary 'a') ) AND (`id3` < _binary '9990') ) or ( (`id1` = _binary 'd') and (`id2` = _binary 'a') and (`id3` = _binary '9990') ) ) order by `id1` asc, `id2` asc, `id3` asc limit 1 offset 99
    展开

    作者回复: 这种写法是我能想到的,在这个场景下最好的方法。 👍👍

    
    
  • 叶明
    2024-10-09 来自江苏
    联合主键的最小和最大值比较容易确定,比如我这里的最小值 ('a', 'a', '1'),最大值 ('d', 'a', '9990'),不能通过 id1>='a' and id2>='a' and id3>='1' 以及 id1<='d' and id2<='a' and id3 <= '9990' 来进行数据分片, 这是因为这三个字段作为联合主键,三个字段作为一个整体是有序的,但细化到 id2, id3 字段,则是当前面字段的值固定时,后面的字段才是有序的,如果按照 id1>='a' and id2>='a' and id3>='1' 去匹配,那么会漏掉一些数据。 我想到的一种方式是将联合字段作为一个整体去匹配,例如 (id1, id2, id3) >= ('a', 'a', '1')。

    作者回复: 是的。你想的这种方式,(id1, id2, id3) >= ('a', 'a', '1') 我也尝试过,这种写法MySQL好像会全表扫描。😭😭

    
    
  • ls
    2024-10-09 来自上海
    循环主键,根据主键去批量更新1000行,每1000行提交一次。是不是就可以了

    作者回复: 这也是一种解法,避免了分页SQL。不过要注意,客户端要使用流式处理,不要一次性把整个表的数据都缓存在客户端。

    
    