1. 参数是子查询时,使用EXISTS代替IN
(1)如果连接列(id)上建立索引,那么查询B表时不用查实际的表,只需要查索引就可以了
(2)如果使用EXISTS,那么只要查到一行数据满足条件就会终止查询,不用像使用IN时一样扫描全表。在这一点上NOT EXISTS也是一样。
2. 参数是子查询时,使用连接代替IN
连接表至少能用到一张表的id列上的索引。而且因为没有子查询,也不会产生中间表。但如果连接没有用索引,可能EXISTS性能会更好
数据库首先会执行子查询,然后将结果存储在一张临时的工作表里(内联视图)接着再扫描整个视图
Oracle数据库中,如果使用建有索引的列,即使使用IN也会先扫描索引
PostgreSQL从版本7.4起也改善了使用子查询作为IN谓词参数时的查询速度。
3.避免排序
具有代表性的排序运算:
- GROUP BY
- ORDER BY
- 聚合函数(SUM,COUNT,AVG,MAX,MIN)
- DISTINCT
- 集合运算符(UNION,INTERECT,EXCEPT)
- 窗口函数(RANK,ROW_NUMBER等)
(1)灵活使用集合运算符的ALL可选项
union ALL 因为不用排除重复数据,所以也不需要进行排序
(2)使用EXISTS代替DISTINCT
exists不进行排序且不做全表扫描
(3)在极值函数中使用索引(MAX|MIN)
不是去掉排序而是优化排序前的查找速度
(4)能写在where子句里的条件不要写在having子句里
①GROUP BY子句聚合时会进行排序或者散列运算,先在where中筛选出来一部分数据,减轻负担
②在where字句中可以用到索引。having是针对聚合后生成的视图进行筛选,大多数情况下聚合后的视图并没有继承原表的索引
4.是否用列索引
(1)索引列运算
在索引列上做+,-,*,/运算会导致索引失效
select * from semoTable where col1*1.1 > 100; ×
select * from someTable where col1>100/1.1; √
(2)索引失效的场景
①用IS NULL或IS NOT NULL
②<>, !=, NOT IN
③使用OR
(3)最左匹配
存在联合索引col1,col2,col3(√标识使用到索引,×标识没有用到索引)
select * from table where col1=10 and col2=100 and col3=200; √
select * from table where col1=10 and col2=100; √
select * form table where col1=10 and col3=200; ×
select * from table where col2=100 and col3=200; ×
最左匹配原则:联合索引的第一列必须写在查询条件的开头,并且索引中列的顺序不能颠倒
使用like,只有前方一致的匹配才能用到索引
select * from table where col1 like 'x%'; √
5.类型转换
默认的类型转换不仅会增加额外的性能开销,还会导致索引不可用
select * from table where col1=CAST(10,AS CHAR(2))