笔记

发布时间 2023-11-01 17:35:03作者: 雾霭雾海

MySQL单表多大进行分库分表?
目前主流的有两种说法:
MySQL 单表数据量大于 2000 万行,性能会明显下降,考虑进行分库分表。
阿里巴巴《Java 开发手册》提出单表行数超过 500 万行或者单表容量超过 2GB,才推荐进行分库分表。
事实上,这个数值和实际记录的条数无关,而与 MySQL 的配置以及机器的硬件有关。因为MySQL为了提高性能,会将表的索引装载到内存中。在InnoDB buffer size 足够的情况下,其能完成全加载进内存,查询不会有问题。但是,当单表数据库到达某个量级的上限时,导致内存无法存储其索引,使得之后的 SQL 查询会产生磁盘 IO,从而导致性能下降。当然,这个还有具体的表结构的设计有关,最终导致的问题都是内存限制。

某个表有近千万数据,查询比较慢,如何优化?
当MySQL单表记录数过大时,数据库的性能会明显下降,一些常见的优化措施如下:
合理建立索引。在合适的字段上建立索引,例如在WHERE和ORDER BY命令上涉及的列建立索引,可根据EXPLAIN来查看是否用了索引还是全表扫描索引优化,SQL优化。
索引要符合最左匹配原则等,参考:https://topjavaer.cn/database/mysql.html#什么是覆盖索引
建立分区。对关键字段建立水平分区,比如时间字段,若查询条件往往通过时间范围来进行查询,能提升不少性能利用缓存。
利用Redis等缓存热点数据,提高查询效率限定数据的范围。比如:用户在查询历史信息的时候,可以控制在一个月的时间范围内读写分离。
主从读写分离,主库负责写,从库负责读通过分库分表的方式进行优化,主要有垂直拆分和水平拆分数据异构到es冷热数据分离。几个月之前不常用的数据放到冷库中,最新的数据比较新的数据放到热库中升级数据库类型,换一种能兼容MySQL的数据库(OceanBase、TiDB等)


索引有什么分类?
1、主键索引:名为primary的唯一非空索引,不允许有空值。
2、唯一索引:索引列中的值必须是唯一的,但是允许为空值。唯一索引和主键索引的区别是:唯一索引字段可以为null且可以存在多个null值,而主键索引字段不可以为null。唯一索引的用途:唯一标识数据库表中的每条记录,主要是用来防止数据重复插入。创建唯一索引的SQL语句如下:
ALTER TABLE table_name
ADD CONSTRAINT constraint_name UNIQUE KEY(column_1,column_2,...);
3、组合索引:在表中的多个字段组合上创建的索引,只有在查询条件中使用了这些字段的左边字段时,索引才会被使用,使用组合索引时需遵循最左前缀原则。
4、全文索引:只能在CHAR、VARCHAR和TEXT类型字段上使用全文索引。5、普通索引:普通索引是最基本的索引,它没有任何限制,值可以为空。

什么是聚集索引?
InnoDB使用表的主键构造主键索引树,同时叶子节点中存放的即为整张表的记录数据。聚集索引叶子节点的存储是逻辑上连续的,使用双向链表连接,叶子节点按照主键的顺序排序,因此对于主键的排序查找和范围查找速度比较快。聚集索引的叶子节点就是整张表的行记录。InnoDB 主键使用的是聚簇索引。聚集索引要比非聚集索引查询效率高很多。对于InnoDB来说,聚集索引一般是表中的主键索引,如果表中没有显示指定主键,则会选择表中的第一个不允许为NULL的唯一索引。如果没有主键也没有合适的唯一索引,那么InnoDB内部会生成一个隐藏的主键作为聚集索引,这个隐藏的主键长度为6个字节,它的值会随着数据的插入自增。
什么是覆盖索引?
select的数据列只用从索引中就能够取得,不需要回表进行二次查询,也就是说查询列要被所使用的索引覆盖。对于innodb表的二级索引,如果索引能覆盖到查询的列,那么就可以避免对主键索引的二次查询。不是所有类型的索引都可以成为覆盖索引。覆盖索引要存储索引列的值,而哈希索引、全文索引不存储索引列的值,所以MySQL使用b+树索引做覆盖索引。对于使用了覆盖索引的查询,在查询前面使用explain,输出的extra列会显示为using index。比如user_like 用户点赞表,组合索引为(user_id, blog_id),user_id和blog_id都不为null。
explain select blog_id from user_like where user_id = 13;

20231101以上转自 https://www.zhihu.com/question/439988021