一、数据库优化法则
二、数据库优化之SQL语句
- (一)操作符
- (二)SQL书写
- (三)SQL语句中索引利用
- (四)更多
三、数据库优化之表结构
- (一)列类型
- (二)字符编码
- (三)适度拆分
- (四)适度冗余
四、数据库优化之索引
- (一)索引设计
- (二)索引副作用
- (三)索引是否越多越好
五、数据库优化之缓存
- (一)Query Cache
- (二)Binlog Cache
- (三)Key Buffer
- (四)innodb_buffer_pool_size
- (五)innodb_log_buffer_size
六、数据库优化之存储引擎
- (一)Mysiam
- (二)InnoDB
- (三)NDBCluster
一、数据库优化法则
- (一)减少数据库访问
- (二)返回更少数据
- (三)减少交互次数
- (四)减少数据库服务器CPU运算
- (五)利用更多资源
二、数据库优化之SQL语句
(一)操作符
- (a) IN 操作符
用in操作,数据库会转换成一个多表的连接,如果转换不成功才先执行IN里面的子查询,再查询外层的表记录,如果转换成功则直接采用多个表的连接方式查询。由此可见用IN的SQL至少多了一个转换的过程。
推荐方案:在业务密集的SQL当中尽量不采用IN操作符,用EXISTS 代替。
(b) NOT IN操作符
此操作是强烈不推荐使用的,因为它不能应用表的索引。
推荐方案:用NOT EXISTS 方案代替
(c) IS NULL 或IS NOT NULL操作
判断字段是否为空是不会应用索引的,因为索引是不索引空值的。不能用null作索引,任何包含null值的列都将不会被包含在索引中。即使索引有多列这样的情况下,只要这些列中有一列含有null,该列就会从索引中排除。也就是说如果某列存在空值,即使对该列建索引也不会提高性能。任何在where子句中使用is null或is not null的语句优化器是不允许使用索引的。
推荐方案:用其它相同功能的操作运算代替,如:a is not null 改为 a>0 或a>’’等。
(d) > 及 < 操作符
大于或小于操作符一般情况下是不用调整的,因为它有索引就会采用索引查找,但有的情况下可以对它进行优化,如一个表有100万记录,一个数值型字段A,99万记录的A=2,1万记录的A=3。那么执行A>2与A>=3的效果就有很大的区别了,因为A>2时数据库会先找出为2的记录索引再进行比较,而A>=3时数据库则直接找到=3的记录索引。
(e) UNION操作符
UNION在进行表链接后会筛选掉重复的记录,所以在表链接后会对所产生的结果集进行排序运算,删除重复的记录再返回结果,如果表数据量大的话可能会导致用磁盘进行排序。实际大部分应用中是不会产生重复的记录。
推荐方案:
采用UNION ALL操作符替代UNION,因为UNION ALL操作只是简单的将两个结果合并后就返回。
(f) Order by语句
ORDER BY语句决定了数据库如何将返回的查询结果排序。Order by语句对要排序的列没有什么特别的限制,也可以将函数加入列中。
但是任何在Order by语句的非索引项或者有计算表达式都将降低查询速度。
解决这个问题的办法就是重写order by语句以使用索引,也可以为所使用的列建立另外一个索引,同时应绝对避免在order by子句中使用表达式。
(g) NOT
我们在查询时经常在where子句使用一些逻辑表达式,如大于、小于、等于以及不等于等等,也可以使用and(与)、or(或)以及not(非)。NOT可用来对任何逻辑运算符号取反。下面是一个NOT子句的例子:
... where not (status ='VALID')
如果要使用NOT,则应在取反的短语前面加上括号,并在短语前面加上NOT运算符。NOT运算符包含在另外一个逻辑运算符中,这就是不等于(<>)运算符。换句话说,即使不在查询where子句中显式地加入NOT词,NOT仍在运算符中,见下例:
... where status <>'INVALID';
对这个查询,可以改写为不使用NOT:
select * from employee where salary<3000 or salary>3000;
虽然这两种查询的结果一样,但是第二种查询方案会比第一种查询方案更快些。第二种查询允许Oracle对salary列使用索引,而第一种查询则不能使用索引。
(二)SQL书写
WHERE子句后面的条件顺序对大数据量表的查询会产生直接的影响。如:
select * from A where a = 'aaa' and b=1
select * from A where b=1 and a = 'aaa'
以上两个SQL中a,b两个字段都没进行索引,所以执行的时候都是全表扫描,第一条SQL的a = 'aaa'条件在记录集内比率为99%,而b=1的比率只为0.5%,在进行第一条SQL的时候99%条记录都进行a及b的比较,而在进行第二条SQL的时候0.5%条记录都进行a及b的比较,以此可以得出第二条SQL的CPU占用率明显比第一条低。
(三)SQL语句中索引利用
采用函数处理的字段不能利用索引。
(四)更多
(1) WHERE子句中的连接顺序:
数据库采用自下而上的顺序解析WHERE子句,根据这个原理,表之间的连接必须写在其他WHERE条件之前, 那些可以过滤掉最大数量记录的条件必须写在WHERE子句的末尾。
(2) SELECT子句中避免使用 *:
解析的过程中, 会将*依次转换成所有的列名, 而这个工作是通过查询数据字典完成的, 这意味着将耗费更多的时间。
(3) 用Where子句替换HAVING子句:
避免使用HAVING子句,HAVING 只会在检索出所有记录之后才对结果集进行过滤.。这个处理需要排序、总计等操作。如果能通过WHERE子句限制记录的数目,那就能减少这方面的开销。