数据库优化
垂直分割
“垂直分割”是一种把数据库中的表按列变成几张表的方法,这样可以降低表的复杂度和字段的数目,从而达到优化的目的。
示例一:在Users表中有一个字段是家庭地址,这个字段是可选字段,而在数据库操作的时候除了个人信息外,并不需要经常读取或是改写这个字段。那么,为什么不把它放到另外一张表中呢? 这样会让你的表有更好的性能。大量的时候,对于用户表来说,只有用户ID,用户名,口令,用户角色等会被经常使用。小一点的表总是会有好的性能。
项目中有一张主表用于存储各种业务的处理情况(包括调用是否成功、时间、业务类型、柜员号等),通过公用的dao层操作获取各业务场景的任务列表查询;各业务场景有各自的业务表,用于存储更多具体详尽的信息(包括调用第三方时的返回报文,如开户及签约接口会返回哪些成功哪些失败及失败原因,用于问题追踪)。
示例二: 有一个叫 “last_login” 的字段,会在每次用户登录时被更新。但是,每次更新时会导致该表的查询缓存被清空。所以,可以把这个字段放到另一个表中,这样就不会影响对用户 ID,用户名,用户角色的不停地读取了,因为查询缓存会帮你增加很多性能。(涉及到mybatis二级缓存?)另外,需要注意的是,这些被分出去的字段所形成的表,你不会经常性地去join他们,否则,这样的性能会比不分割时还要差,而且,会是指数级的下降。
二级缓存工作模式
选择正确的存储引擎
在 MySQL 中有两个存储引擎 MyISAM 和 InnoDB,每个引擎都有利有弊。MyISAM 适合于一些需要大量查询的应用,但其对于有大量写操作并不是很好。甚至你只是需要update一个字段,整个表都会被锁起来,而别的进程,就算是读进程都无法操作直到读操作完成。另外,MyISAM 对于 SELECT COUNT(*) 这类的计算是超快无比的。
InnoDB 的趋势会是一个非常复杂的存储引擎,对于一些小的应用,它会比 MyISAM 还慢。但它支持“行锁” ,于是在写操作比较多的时候,会更优秀。并且,他还支持更多的高级应用,比如:事务。
随着InnoDB的优化与发展,一般都选择mysql默认的InnoDB。
mysql行锁、表锁
拆分大的 DELETE 或 INSERT 语句
如果你需要在一个在线的网站上去执行一个大的DELETE 或 INSERT 查询,你需要非常小心,要避免你的操作让你的整个网站停止响应。因为这两个操作是会锁表的,表一锁住了,别的操作都进不来了。Apache 会有很多的子进程或线程。所以,其工作起来相当有效率,而我们的服务器也不希望有太多的子进程,线程和数据库链接,这是极大的占服务器资源的事情,尤其是内存。如果你把你的表锁上一段时间,比如30秒钟,那么对于一个有很高访问量的站点来说,这30秒所积累的访问进程/线程,数据库链接,打开的文件数,可能不仅仅会让WEB服务Crash,还可能会让整台服务器马上挂了。所以,如果有一个大的处理,一定把其拆分,使用 LIMIT 条件是一个好的方法。下面是一个示例:
while (1) {
//每次只做1000条
mysql_query("DELETE FROM logs WHERE log_date <= '2009-11-01' LIMIT 1000");
if (mysql_affected_rows() == 0) {
// 没得可删了,退出!
break;
}
// 每次都要休息一会儿
usleep(50000);
}
项目中删除排队机客户信息时,每次删除5000条,若返回值大于等于5000则再次执行删除动作。
delete from (
select * from table where ADD_TIME between #{beginTime} and #{endTime} fetch first 40000 rows ONLY
)
合理的冗余
完全按照规范化设计的系统几乎是不可能的,除非系统特别的小,在规范化设计后,有计划地加入冗余是必要的。
冗余可以是冗余数据库、冗余表或者冗余字段,不同粒度的冗余可以起到不同的作用。
冗余可以是为了编程方便而增加,也可以是为了性能的提高而增加。从性能角度来说,冗余数据库,如集群可以分散数据库压力,双机热备保证高可用性(互为备份的两台服务器共同执行同一服务,其中一台主机为工作机(Primary Server),另一台主机为备份主机(Standby Server)。在系统正常情况下,工作机为应用系统提供服务,备份机监视工作机的运行情况(一般是通过心跳诊断,工作机同时也在检测备份机是否正常),当工作机出现异常,不能支持应用系统运营时,备份机主动接管工作机的工作,继续支持关键应用服务,保证系统不间断的运行);冗余表可以分散数据量大的表的并发压力,也可以加快特殊查询的速度;冗余字段可以有效减少数据库表的连接,提高效率。
Mysql双机热备实现
PreparedStatement 替代Statement
1.性能更高,因为数据库对SQL语句的语法检查,语义分析、编译、优化在第一次执行时已经完成,执行计划会被缓存起来;
2.避免sql注入。
尽量去除外键约束
有外键约束会影响插入和删除性能,如果程序能够保证数据的完整性,那在设计数据库时就去掉外键。
其他方面
(1)提升数据库服务器硬件配置,配置mysql性能优化参数,或者搭建数据库集群。
(2)从系统层面增强mysql的性能:优化数据表结构、字段类型、字段索引、分表,分库、读写分离等等。
(3)从数据库层面增强性能:优化SQL语句,合理使用字段索引。
(4)从代码层面增强性能:使用缓存和NoSQL数据库方式存储,如MongoDB/Memcached/Redis来缓解高并发下数据库查询的压力。
(5)减少数据库操作次数,尽量使用数据库访问驱动的批处理方法。
(6)不常使用的数据迁移备份,避免每次都在海量数据中去检索。