为何要对Mysql进行分表分库
- 单表性能不足以支撑业务场景.
- 存储空间不足.
- 单库单表在记录达到一定程度时性能会极速下降.
- 服务可靠性.
除了第3点,其他都比较好理解.
为何记录数多会导致单表性能下降
此处以Mysql的InnoDB引擎的基础上讲解.
InnoDB的索引采用B+Tree,结构如下:
非叶子节点不存放数据,数据只存放与叶子节点.
这种结构的查询速度稳定,IO次数在树干能被完全加载到内存时,只需要1次,性能非常好.
但性能问题也出现在此处.
如果Mysql服务的内存不足以完全加载树干(非叶子结点),此时容易出现频繁进行磁盘IO来查找索引和数据节点.
此外,树高也是影响IO次数的重要原因.
B+Tree的树高度由单个节点大小及存储单位有关.
InnoDB中,最小存储单位是页(Page)
,默认大小是16KB
.
单个节点大小由: 指针
和主键
大小组成,指针大小为6B,主键由实际设计表时指定,如果是int
则为4B,bigint
为8B.
Node = 6B + 4/8B = 10/14B
这样单页能存储:
16KB / 10B = 1600个指针和主键组合.
所以:
1层高度能存储1,600条记录,索引内存116KB.
2层能存储2,560,000条记录,索引内存1.6K16KB=25.6KB.
3层存存储4,096,000,000条记录,索引内存2.56M16KB=40.96MB.
4层存存储6,553,600,000,000条记录,索引内存4G16KB=64GB.
OK,算到这里,应该有感觉了吧.
数据库服务器需要至少64GB的内存才能完全装载树深为4的单表的所有索引数据.
如果该数据库还有其他表,则可用内存更小.
如果该数据库服务有100张表,每张40亿条记录(主键为bigint
的为21亿的为记录),则完全加载索引需要40GB的内存空间,完全不够用.
同时在实际生产环境,需要留有一定余量,分表分库需要提前安排.