✅MySQL千万级数据量,查询如何做优化?

✅MySQL千万级数据量,查询如何做优化?

典型回答

千万级数据量, 听着好像挺大的,但是其实,可以非常明确的告诉大家,对于MySQL来说,单库单表对2000万以内的数据查询,甚至再多一点,5000万以内的数据查询,只要注意一下几点,就可以做到非常高性能的查询,而不需要去做分库分表,也不需要用ES,更不用分布式数据库:

索引优化

索引!一定是最立竿见影的优化手段。有索引和没索引,一个SQL能命中和不能命中索引,性能差异是天差地别的。所以,针对千万级数据量的表,索引的使用是至关重要的。在使用索引时,以下几个方面需要考虑和注意:

1、索引类型选择:大多数情况下我们都是用B+树索引,但是hash索引并不是完全没有可取之处,他在等值查询上面还是非常有优势的。所以,如果你的某一张表,不要做排序、范围查询等,只需要做等值查询的话,是可以考虑使用hash索引的。

✅InnoDB中的索引类型?

2、联合索引:一个key的索引肯定不如多个key的索引效果要好,对于索引来说,前缀长度越长,效果一般是越好的。所以,对于有很多个查询条件的语句比较多的情况下,可以考虑构建联合索引,把这些相关的key放在一起,这样可以大大提升查询性能。

3、索引覆盖,有了联合索引之后,就可以用到索引覆盖了。索引覆盖非常容易,只需要你写SQL的时候,通过索引的key去查询其他的key就行了。只不过where中的key要遵守最左前缀匹配而已。用了索引覆盖,就可以避免回表,就可以大大的提升查询性能。

✅什么是索引覆盖、索引下推?

4、避免索引失效。有的时候建立索引并不一定就能用的上索引,很多时候会导致索引失效了,你以为走了索引,但是实际上并没走,所以需要注意。比如一些常见的函数、类型不一致、不遵守最左前缀等等,都是可能会导致索引失效的。一定要通过执行计划来确认是不是走了索引,以及走对了索引。

✅索引失效的问题是如何排查的,有那些种情况?

5、选择区分度高的字段作为索引。这样查询的效果才会好,但是也不绝对,有些场景也要特殊考虑,还要考虑索引的过滤效果。

✅区分度不高的字段建索引一定没用吗?

避免多表JOIN

多表的JOIN是非常影响性能的,我们需要尽可能的避免他,可以通过适当的冗余字段来减少join的情况。另外,如果一定要join,那么也要用小表驱动大表,并且用索引作为关联条件。

✅为什么大厂不建议使用多表join?

✅MySQL 为什么是小表驱动大表,为什么能提高查询性能?

避免使用select *

我们在做基本查询到时候,应该查询那些我们关心的字段,不要图方便直接select *,这样不仅没办法用到索引覆盖,还会因为查询的字段太多导致更多的磁盘IO,导致性能下降。

避免深分页

✅MySQL单表一千万条数据怎么做分页查询?

降低事务的粒度

有的时候,如果一个事务中干的活太多,就会导致一个长事务,而长事务有很多危害,其中比较典型的就是占用数据库链接。

大家要知道,一个数据库的连接数是有限的,尤其是他给单台服务器分配的连接数更是非常有限的,所以,我们不能浪费这些连接,应该尽可能的降低事务的粒度,减少数据库连接的占用。

使用缓存

对于千万级的数据量的系统来说,上缓存基本上是必不可少的了。针对一些查询情况,可以通过缓存来减少查询的次数,提升性能。

但是不建议大家直接用数据库的缓存和mybatis的缓存,而是建议大家直接用redis这样的分布式缓存。这样我们就可以避免很多黑盒,因为我们可以明确的知道这里有缓存。

数据归档

对于千万级数据量,不可能所有的数据都是热数据,所谓热数据就是会经常查询的数据,比如交易订单,一般6个月前的订单很少有人再去查询他了。

所以我们其实可以针对数据做一些定期的归档 ,把他们从当前表中挪出来,放到历史表中,这样当前的库表数据量就会比较少了,就可以有很好的查询性能了。

硬件提升

对于一个数据库来说,他部署的硬件条件不一样,结果肯定也不一样,你部署在4C8G的服务上,和部署在64C512G的服务上,那一定是有很大的差异的。

所以,我们可以适当的通过提升实例的规格,来提升整体的吞吐量。

其他

以上,都干了,基本上抗个几千万的查询没啥问题,至于更新和插入操作,那就也需要考虑锁、热点行等等问题,这是另外的话题。

如果以上这些都干了,还是解决不了问题,那么再考虑分库分表、以及上搜索引擎。

✅如果单表数据量大,只能考虑分库分表吗?