故事背景
在八股文中,说到如何进行数据库的优化,除了基本的索引优化,经常会提到分库分表,说是如果业务量剧增,数据库性能会到达瓶颈,如果单表数据超过两千万,数据查询效率就会变低,就要引入分库分表巴拉巴拉。
我同事也问我,我们数据表有些是上亿数据的,为什么不用分库分表,如果我没接触过分库分表我也会觉得大数据表就要分库分表呀,这是八股文一直以来教导的东西。但是我就跟他说,分库分表很坑爹,最近才让我遇到一个BUG......
系统复杂度upup
业务中有个设备表数据量很大,到现在为止已经有5、6亿数据了。在4年前,前人们已经尝试了分库分表技术,分了4个库,5个表,我只是负责维护这个业务发现他们用了分库分表。但是在查询表数据的时候看到是查询ES的,我就问为什么要用ES?
同事回答查询分库分表一定要带分片才能走到路由,否则会查询全部库和全部表,意思是不查分片字段,单表只用一个SQL,但是分库分表要用20个SQL.....所以引入了ES进行数据查询。
但是引入ES之后又引入一个新的问题,就是ES和数据库的数据同步问题。他们使用了logstash做数据同步,但不是实时的,在logstash设置了每20秒同步一次。
因为要使用分库分表,引入了shardingjdbc,因为查询方便引入了es,因为要处理数据同步问题引入了logstash......所以系统复杂度不是高了一点半点,之前发现有个字段长度设置小了,还要改20张表。
分页问题
最近遇到一个奇怪的bug,在一个设备的单表查询翻页失败,怎么翻都只显示第一页的数据,一开始我以为是分页代码有问题,看了半天跟其他表是一样的,其他表分页没问题,见鬼了。后面再细看发现这个单表的数据源是设备数据源,用的是shardingjdbc的配置。
之前就看过shardingjdbc有一些sql是不支持的,怀疑就是这个原因,百度了一下果然是有bug。
想了一下有两个解决办法,第一个是升级shardingjdbc的版本,据说是4.1之后修复了该问题,但是还没有尝试。
第二个办法是把分库分表业务的数据源跟单表区分开,单表业务使用普通的数据源后分页数据正常显示。
关于数据库优化
一般来说数据库优化,可以从几个角度进行优化:
unset
unset
1、硬件优化
unset
unset
1) 提升存储性能
-
使用SSD:替换传统机械硬盘(HDD),SSD能提供更快的随机读写速度。
-
增加存储带宽:采用RAID(推荐RAID 10)提高数据存储的读写速度和冗余。
-
内存扩展:尽量让数据库缓存更多的数据,减少IO操作。
2) 增强CPU性能
-
-
分析数据库对CPU的利用情况,确保不被CPU性能瓶颈限制。
3) 提高网络带宽
-
优化服务器与客户端之间的网络延迟和带宽,尤其是分布式数据库的场景中。
-
unset
unset
2、软件层面优化
unset
unset
1) 数据库配置
-
调整数据库缓冲池(Buffer Pool)的大小,确保能缓存大部分热数据。
-
优化日志文件的写入(如MySQL中调整
innodb_log_buffer_size
)。
-
使用内存数据库或缓存技术(如Redis、Memcached)加速访问速度。
2) 分布式架构
-
对于高并发需求,采用分布式数据库(如TiDB、MongoDB)进行读写分离或数据分片。
3) 数据库索引
-
选择合适的索引类型:如B+树索引、哈希索引等,根据查询特点选择适配的索引。
-
4) 数据库版本升级
-
保持数据库版本为最新的稳定版本,利用最新的优化特性和Bug修复。
unset
unset
3. SQL层面优化
unset
unset
1) 查询优化
-
减少不必要的字段:只查询需要的列,避免使用
SELECT *
。
-
加速排序和分组:在
ORDER BY
和
GROUP BY
字段上建立索引。
-
拆分复杂查询:将复杂的SQL分解为多个简单查询或视图。
-
分页查询优化:如避免大OFFSET分页,可以使用索引条件替代(如
WHERE id > last_seen_id
)。
2) 合理使用索引
-
对频繁用于WHERE、JOIN、GROUP BY等的字段建立索引。
-
3) 减少锁定
4) SQL调优工具
-
使用数据库自带的分析工具(如MySQL的EXPLAIN、SQL Server的性能监控工具)来分析查询计划并优化执行路径。
unset
unset
4. 综合优化
unset
unset
-
定期进行性能分析:定期查看慢查询日志,优化慢查询。
-
清理历史数据:对于不再使用的历史数据,可存储到冷数据仓库,减少主数据库的负载。
-
使用连接池:通过数据库连接池(如HikariCP)管理和复用连接,降低创建和销毁连接的开销。
unset
unset
tips:
unset
unset