hnwyllmm / snip

snip code
1 stars 0 forks source link

测试一下中文翻译成英语是否好用 #3

Open hnwyllmm opened 2 months ago

hnwyllmm commented 2 months ago

Describe your question

Question

我看官方文档中存在如下描述:

ob-spec

如果有一个电商 SaaS,【订单表】有 商户ID( int ) 和 订单号( varchar(32) ) 存在唯一约束,这个时候我们也应该用 这两个字段 做联合主键吗?

众所周知,MySQL 采用的是 B+Tree 的结构来存储数据,一般建议 ID是自增的,这样可以避免随机插入,导致 MySQL 数据页频繁分裂,进而导致检索数据时 IO 开销增加。

然而,商户ID + 订单号 也很明显不是自增的,所以我才有此疑问。 对于这种场景,如果 OceanBase 仍然推荐使用它们联合作为主键,是因为 LSM-Tree 能够很好地处理 裂页 问题么 ?

此外,除了主键索引,我们一般还会额外在关键业务表上创建几个二级索引。 在 MySQL 中,因为每个二级索引的叶子节点都会存储相应行的主键值。所以,如果主键较大,那么每个二级索引的叶子节点所需的空间也会更大,因为它们需要存储更大的主键值。

如果主键是 bigint 的自增ID,在每个二级索引上存储,关联主键也就占用 8个字节 的空间。 如果主键是 int + varchar(32) 这种联合索引,是不是就意味着,关联主键也要占用至少 4+32 个字节的空间呢? 如果有多个二级索引(一般2~4个),是不是也要重复多占用不少空间 ?这样的话,存储空间 以及 维护这些二级索引的开销不是也增大了许多么 ?

Environment

OB Version(LD_LIBRARY_PATH=../lib:$LD_LIBRARY_PATH ./observer -V)

Hardware parameter(uname -a)

Other information

No response

hnwyllmm commented 2 months ago

不按顺序回答你的问题。 先说“如果主键是 int + varchar(32) 这种联合索引,是不是就意味着,关联主键也要占用至少 4+32 个字节的空间呢?” --> 在OceanBase 中 int也是按照8位来存储的,所以这里应该就是 8+32=40字节,一条数据比bigint自增ID多了32个字节。按照1亿个数据量来算,就多了大概3G的存储。如果有3个索引,也不过10G的存储。先不说你肯定不在乎这10G的存储空间(毕竟业务量都上亿了),OceanBase在存储时还会压缩的,最终的数据,即使是多副本,也通常比MySQL占用的存储空间少了50%,具体可以看看官网上的一些案例描述,或许会有案例可以帮到你们。


再看“自增ID作为主键”的问题,在分布式数据库上这是一个老生常谈的话题,看看gpt的回答:

写入热点:自增主键意味着新插入的行总是拥有比之前高的主键值。这在分布式数据库中可能会造成主键值集中在某个范围内,从而导致所有新的插入操作都集中在特定的分区或节点上。这种情况创建了所谓的“写入热点”,可能会降低系统的性能和扩展性。

分布式事务冲突:在分布式系统中保持主键的唯一自增值需要跨多个节点协调,这可能会导致无法避免的分布式事务冲突和协调开销。同步自增值可能会导致延迟和额外的性能损耗。

扩展性限制:自增主键强制了数据的插入顺序,这可能导致数据在物理存储上的不均匀分布,对于需要水平扩展的分布式数据库来说,这是一个不利因素。扩展操作需要平衡和迁移数据,而自增主键可能会使这一过程更加复杂和低效。


网上也有很多自增主键的博客。大概意思都是自增主键在非分区数据库上都挺和谐,但是分区数据库上很困难。 对此,OceanBase还对自增列做了优化,参考自增 noorder 模式:https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000000751258


在来看“对于这种场景,如果 OceanBase 仍然推荐使用它们联合作为主键,是因为 LSM-Tree 能够很好地处理 裂页 问题么 ?” LSM-Tree不像B+树,没有列页的问题。新来的数据更新,不管是新增、更新还是删除,都是先在内存上操作的。在一定的平衡场景下,性能不会受到“数据太分散”相关的影响。而LSM的合并操作,都是在后台进行的。