分库分表
- 根据id范围分表
-
- 涉及写热点表问题
- 根据id取模分表
-
- 数据均匀分布
-
- 扩展还要涉及数据迁移
- 范围 + 取模
读扩散问题
我们上面提到的好几种分表方式,都用了id这一列作为分表的依据,这其实就是所谓的分片键。
实际上我们一般也是用的数据库主键作为分片键。
这样,理想情况下我们已知一个id,不管是根据哪种规则,我们都能很快定位到该读哪个分表。
但很多情况下,我们的查询又不是只查主键,如果我的数据库表有一列name,并且加了个普通索引。
这样我执行下面的sql
select * from user where name = "小白";
由于name并不是分片键,我们没法定位到具体要到哪个分表上去执行sql。
于是就会对所有分表都执行上面的sql,当然不会是串行执行sql,一般都是并发执行sql的。
如果我有100张表,就执行100次sql。
如果我有200张表,就执行200次sql。
随着我的表越来越多,次数会越来越多,这就是所谓的读扩散问题。
-
引入映射表 并用 查询条件作为分片键
-
-
通过引入一个新表,倒过来,先用name查到对应的id,再拿id去获取具体的数据。这其实就像是建立了一个新的索引一样,像这种,通过name列反查原数据的思想,其实就很类似于倒排索引。
-
-
引入es,查询通过es 查询
-
-
引入tidb,实际上tidb对于读扩散也是通过引入映射分片表实现的
总结
- mysql在单表数据过大时,查询性能会变差,因此当数据量变得巨大时,需要考虑水平分表。
- 水平分表需要选定一个分片键,一般选择主键,然后根据id进行取模,或者根据id的范围进行分表。
- mysql水平分表后,对于非分片键字段的查询会有读扩散的问题,可以用普通索引列作分片键建一个新表,先查新表拿到id后再回到原表再查一次原表。这本质上是借鉴了倒排索引的思路。
- 如果想要支持更多维度的查询,可以监听mysql的binlog,将数据写入到es,提供近实时的查询能力。
- 当然,用tidb替换mysql也是个思路。tidb属实是个好东西,不少厂都拿它换个皮贴个标,做成自己的自研数据库,非常推荐大家学习一波。
- 不要做过早的优化,没事别上来就分100个表,很多时候真用不上