一、建立合适的索引
在常用过滤条件、表连接的字段建立索引。但并不是所有索引对查询都有效,MySQL如果扫描数据超过30%,都会走全表。
二、在where条件中优化
1.Oracle数据库where条件是从后往前执行,和MySQL数据库顺序相反,可把大过滤的条件放在最先执行的位置
2.避免在 where 子句中使用 or 、表达式操作、函数操作、 !=或<> 操作符、前置百分号等5种情况,否则将导致引擎放弃使用索引而进行全表扫描
select id from t where num=10 or num=20
可以这样查询:
select id from t where num=10
union all
select id from t where num=20
select id from t where num/2=100
应改为:
select id from t where num=100*2
select id from t where substring(name,1,3)='abc' --name以abc开头的id
select id from t where datediff(day,createdate,'2005-11-30')=0 --'2005-11-30'生成的id
应改为:
select id from t where name like 'abc%'
select id from t where createdate>='2005-11-30' and createdate<'2005-12-1'
select id from t where name like ‘%abc%’
若要提高效率,可以考虑全文检索。
3.exists替代in
很多时候用 exists 代替 in 是一个好的选择:
select num from a where num in(select num from b)
用下面的语句替换:
select num from a where exists(select 1 from b where num=a.num)
4.不要使用 select * from t,用具体的字段列表代替“*”,不要返回用不到的任何字段。
三、表连接方式优化,尽量避免NESTED LOOP嵌套循环
一般而言,使用nested loop要用数据量小的表作为驱动表(准确说,应该是经过限制条件后返回结果集行数较少的应作为驱动表)
,这样复杂度O(m*log(n)),即驱动表数据记录m要小。
或者改变join的方式,使用/* +use_hash(t1,t2) */变为hash join,要比nested loop outer快很多。
四、考虑使用临时表或表变量存放中间结果
五、建立分区表
表进行分区后,逻辑上表仍然是一张完整的表,只是将表中的数据在物理上存放到多个表空间(物理文件上),这样查询数据时,不至于每次都扫描整张表。