Java面试题储备11: mysql优化全面讲一下,及你遇到的对应业务场景
有很多很细的点,嗯,我想想
-
首先是遇到大表的查询要加索引提高查询速度,索引最好用区分度高且请求高频的字段,比如订单表里订单id和用户id、用户表里用户id、问卷发放记录表里订单id和用户id,如果某几个字段常常组合查询使用,直接创建复合索引,还有比如主键和外键字段频繁查询时都可添加索引提高查询速度
-
第二个是可以通过explain+sql排查慢sql,可以通过返回的key查看是不是命中了索引,通过filters看过滤了多少数据,通过type看是不是全表扫描
-
项目上遇见个场景,给用户发营销短信,由于短信接口是批量接口,一次性发一万个用户,一个营销用户包上百万用户,会在几分钟内发完,mq接收短信回执时,有大量回执请求更新数据库,导致数据库压力大cpu飙升,为了防止频繁IO,将单条数据更新改为了批量更新,有效降低了IO频率
-
对于某些数据量很大但又需要实时的迅速的查询数据,可以将有效的字段通过binlog消息同步到es存储,es因为分词和多分片的特性,查询性能较好
-
对于某些不需要实时处理的数据,比如我们本地存的用户行为信息表,只需要T+1更新,但是要导出一个大的数据报表,其中涉及到很多表关联查询,这时es就不能支持了,可以使用clickhouse,clickhouse是列式存储的数据库,支持多表关联查询能够保证较好的性能
-
也可以使用定时的job数据任务,通过sql将要处理的结果字段处理出来,更新到一张结果宽表里,查询和导出的时候直接操作宽表
-
如果单表的数据量过大,一般我们的标准是单表数据量超过千万,就要考虑分表,一般通过唯一标识的哈希值取模分表数确定存在哪张表里,如果有明确的唯一键一般使用唯一键的哈希值,比如用户id、订单id;或者如果业务上查询的时候一般都通过时间查询,也可以通过时间分表
-
说到时间,如果数据表中存在大量无效的历史数据,也会损耗数据库性能,需要和业务沟通确认有效期,将超过有效期的数据进行归档处理,可以有效降低数据表大小
-
分库一般不用,我们系统只有通过不同业务处理的时候,比如我们系统一套代码支持了多个小程序,通过业务线的code取哈希值,查询和插入不同的数据库,再根据订单号和用户pin的哈希值取模分表数查询不同数据表