最近因为工作需要用到 Bigtable,而设计一个好的数据库 Schema 对于性能至关重要,因此想找一些资料看看别人是如何根据自身业务特点设计 schema 的。

在网上找到了一篇 GCP 自己的官方文档 , 里面提到了一些 best practice,也提到了哪些坑需要避免,然而还是看的云里雾里。 比如,

Row keys to avoid

Row keys that start with a timestamp. This will cause sequential writes to be pushed onto a single node, creating a hotspot. If you put a timestamp in a row key, you need to precede it with a high-cardinality value like a user ID to avoid hotspotting.

Row keys that cause related data to not be grouped together. Avoid row keys that cause related data to be stored in non-contiguous row ranges, which are inefficient to read together.

说不要用 timestamp 作为 row key 的开头,这样会导致所有的写操作都写到了单个 node 上,但又说,bigtable 中的 row key 都是按照字典排序的,所以如果有查询 range 的需求,那么尽量要让 key 有序。 看到这里感觉这是前后矛盾的。

所以,还是需要了解一下 bigtable 的基本实现原理。

首先从 SSTable 和 LSM Tree 开始。 《DDIA》 书中也有专门的的章节介绍他们,通常,SSTable 和 LSM Tree 会同时出现,但是他们各自负责的功能是不一样的。

SSTable 全称是 Sorted String Table,这是 BigTable 内部用来存储数据的格式,注意,是格式而不是结构,存储数据的结构是 LSM Tree.

LSM Tree 全称是 Log Structured Merge Trees,它最大的创新在于 将随机写转化为顺序写

SSTable

SSTable 是一个持久化的、有序的、不可更改的 Map 结构,Key 和 Value 都是任意的 Byte 串

总的来说它的核心思想是 Append only,就是说所有的写都是追加新的纪录,而不是改变已有的值,并且都是先写到内存,当 size 超过一定大小后,再写入磁盘。

之后,由专门的进程/线程负责把多个文件合并成一个文件,消除重复元素,整个过程类似归并排序