1.服务器层面优化
将数据保存在缓存中,保证从内存中读取
内存预热
降低磁盘写入次数
提高磁盘读写
2.SQ设计层面优化
设计中间表,已针对于统计分析功能,或实时性不高的需求
减少关联查询,创建合理的冗余字段
对于表中不经常使用的字段或存储数据比较多的字段,考虑拆表
每张表建议创建主键(主键索引),且主键类型最好是int,主键自增
3.SQL语句优化
(1)索引优化
(2)其他优化
尽量不适用count(*),尽量使用count(主键)
Join两张表的关联字段创建索引,且最好字段类型一样
where条件中尽量不要使用1=1 not in语句(建议使用 not exists)
不用mysql内置函数,因为内置函数不会建立查询缓存
索引失效
1.如果条件中有or,即使其中有条件带索引也不会使用(这也是为什么尽量少用or的原因)
2.符合索引不符合最左前缀原则
3.like以%开头
4.需要类型转换
5.where中索引列有运算或函数
6.如果mysql觉得全表扫描更快时(数据量少)
什么时候没必要使用索引
1.唯一性差,区分度低的
2.频繁更新的字段
3.where中不用的字段
4索引中使用<>时,效果一般
sql语句优化技巧:
1.尽量使用索引覆盖,避免回表扫描
2.查询语句尽可能简单,大语句拆小语句,减少锁时间;
3.尽量使用数字型字段,若只含数值信息的字段尽量不要设计为字符型;
4.用 exists/or 替代 in 查询;
5.避免在索引列上使用 is null 和 is not null。
6.对于连续数值,使用BETWEEN不用IN,select id from t where num between 1 and 5
7.多表联合查询时,先定义子查询查询目标数据,再使用主查询处理数据的展示
设计层面优化方案:
(1)使用可以存下数据最小的数据类型;
(2)使用简单的数据类型,int 要比 varchar 类型在 MySQL 处理简单;
(3)尽量使用 tinyint、smallint、mediumint 作为整数类型而非 int;
(4)尽可能使用 not null 定义字段,因为 null 占用 4 字节空间;
(5)尽量少用 text 类型,非用不可时最好考虑分表;
(6)尽量使用 timestamp,而非 datetime;
(7)单表不要有太多字段,建议在 20 个字段以内。
(8)VARCHAR的长度只分配真正需要的空间
(9)使用枚举或整数代替字符串类型
(10)用整型存储IP
索引:
性能优化3大问题:
1.单条sql慢
问题分析:索引问题,数据量大
解决方案:
(1)正确使用索引,
(2)拆表:
纵向拆分,列国多,将不常使用的字段另建一张表,将大字段另建一张表
水平拆分,表的行数超过200万行,速度就会变慢
2.部分sql慢
解决方案:开启慢查询,找出具体sql,然后逐条优化。
可以使用如下 MySQL 命令:
mysql> set global slow_query_log=1
不过这种设置方式,只对当前数据库生效,如果 MySQL 重启也会失效,如果要永久生效,就必须修改 MySQL 的配置文件 my.cnf,配置如下:
slow_query_log =1
slow_query_log_file=/tmp/mysql_slow.log
3.整个sql慢
问题分析:当出现整个 SQL 都运行比较慢就说明目前数据库的承载能力已经到了峰值,因此我们需要使用一些数据库的扩展手段来缓解 MySQL 服务器了。
一般情况下数据库都是“读多写少”,换言之就是读取大量数据造成的,我们可以采用数据库集群方式,主库负责写,从库负责读。
解决方案:读写分离
读写分离有两种方案:
1.应用层解决方案
可以通过应用层对数据源做路由来实现读写分离,比如,使用 SpringMVC + MyBatis,可以将 SQL 路由交给 Spring,通过 AOP 或者 Annotation 由代码显示的控制数据源。
优点:路由策略的扩展性和可控性较强。
缺点:需要在 Spring 中添加耦合控制代码。
2.中间件解决方案
通过 MySQL 的中间件做主从集群,比如:Mysql Proxy、Amoeba、Atlas 等中间件都能符合需求。
优点:与应用层解耦。
缺点:增加一个服务维护的风险点,性能及稳定性待测试,需要支持代码强制主从和事务。