数据库优化
数据库性能优化
这里的数据库特指MySQL,在介绍数据库性能优化方法之前,提几个用于性能分析的MySQL命令行工具:
-
mysqlreport
:第三方MySQL状态报告工具,分析结果一目了然 -
explain
:用于分析SQL语句的执行细节(比如是否用到了索引) -
mysqlsla
:用于查询哪些SQL操作的耗时超过了预设的阈值,使用此工具之前需要在my.cnf
开启慢查询日志,即增加long_query_time=1
和log-slow-queries = /data/var/mysql_slow.log
这2行配置项
(1)索引
索引就像是一本书的目录,好的索引可以极大地提升select操作的效率,但会增加delete/update/insert的开销。如果你的数据库的读远多于写,那么索引是非常奏效的。
- 在哪个字段设置索引:经常出现在select语句的where/order by/group by后的字段,都可以考虑设置索引
- 使用组合索引:如果一条select语句的条件过滤中涉及到了多个field,那可以考虑设置组合索引,组合索引有一个最重要的原则就是 最左前缀 ,比如
where A=1 and C=2
是无法使用到A, B, C
组合索引的 - 判断一个SQL操作是否用到索引,可以使用explain工具
(2)冗余设计
数据库的表设计一般遵循所谓的第三范式(3NF),即要求非主键字段之间不能存在依赖关系。但是如果完全按照这样来做的话,SQL语句中会包含大量的join操作。在设计时我们可以保留适量的冗余,比如一个user的blogs数目,可以直接在user表中增加一个blogs_count字段,每次增加/删除blog时就相应地+/-此字段。以后查询起来就快了。
(3)读写分离
单个数据库读写扛不住?那就把读写分离开吧,使用MySQL的主从复制功能,多个从数据库保持与主数据库的同步,然后update/delete/insert全部走主数据库,select则使用负载均衡技术分摊到多个从数据库上。
(4)垂直分区 & 水平分区
读写分离了还是不行,怎么办?可以考虑把相对独立的数据表存放在不同的服务器上,然后每一个都采用读写分离技术,这就是垂直分表,可以进一步将读写压力分摊到更多的服务器上。
如果垂直分表了还不行,那就考虑将单表进一步拆分(分表),然后每n(n>=1)个表部署到独立的服务器上(水平分区)。分表和水平分区的方法大概有:哈希算法、范围分区、映射关系,具体见《构建高性能Web站点》P370页。
(5)NoSQL
如果以上的方法还不奏效,或者虽然奏效但维护成本太高,那就可以考虑抛弃关系数据库,转投NoSQL阵营了。需要注意的是,关系数据库和NoSQL都有各自的适用场景,谁也无法完全取代谁。但NoSQL实在是太多啦,如何选择呢?这里推荐一些比较不错的博文:Robbin的 文章 对NoSQL有一个概览式的分类,草屋主人的NoSQL系列文章 涉及到了各类应用场景,值得一读。