SQL语句优化写法心得 - 条件查询。
个人总结,可以参考一下,不一定正确。
SQL优化写法我想首先要了解一下SQL关键字执行优先级。
SQL关键字优先级:
ON > WHERE > HAVING 这三个条件关键的优先级,SQL解析遇到这三个关键字的时候首先执行ON,其次where,最后才是having。
ON、WHERE:用于内外连接,下面举几个例子说明:
cis.relationship t1 数据为 n条
cis.AGNET_RANK_TMP t2 数据为 m条
/* 1 */
select count(*) cn from cis.relationship t1 left join cis.AGNET_RANK_TMP t2 on t1.upperbuid = '1147281' and t1.id = t2.id ;
/* 2 */
select count(*) cn from cis.relationship t1 left join cis.AGNET_RANK_TMP t2 on t1.id = t2.id and t1.upperbuid = '1147281' ;
说明:1和2的查询不到正确的结果,原因是在left join 、right join中on后面使用常量是无效的,数据库都会忽略掉。cn = 主表数据个数。
/* 3 */
select count(*) cn from cis.relationship t1 left join cis.AGNET_RANK_TMP t2 on t1.id = t2.id where t1.upperbuid = '1147281' ;
/* 4 */
select count(*) cn from cis.relationship t1,cis.AGNET_RANK_TMP t2 where t1.id = t2.id and t1.upperbuid = '1147281' ;
说明:3和4我感觉差不多,查询是t1与t2做 n*m 查询,然后根据where的常量条件做筛选,最终查询次数为2(n*m) 。
select count(*) cn from (select t.id cis.relationship t where t.upperbuid='1147281') t1 left join cis.AGNET_RANK_TMP t2 on t1.id = t2.id ;
说明:先执行子查询(select t.id cis.relationship t where t.upperbuid=’1147281’)得到数据个数为c,然后再left join。最终查询次数为,n+c*m (c
/* 5 */
select count(*) cn from cis.relationship t1 inner join cis.AGNET_RANK_TMP t2 on t1.id = t2.id and t1.upperbuid = '1147281' ;
说明: 这个SQL中是inner join这个之前的left join、right join有所不一样,因为inner join on关键字后面常量条件会起作用。
on关键字的特性,遇到常量会针对t1做一次常量查询c1记录,然后t2做一次常量查询c2记录,之后再字段关联查询。
最终查询次数,n+m+c1*c2 (c1
t1 inner join t2 on t1.id = t2.id and t1.id = '1147281'
和
t1 inner join t2 on t1.id = t2.id and t2.id = '1147281'
是两种不同的概念,当后面在跟着where的时候,结果有时候会不一样的,具体的使用还是根据实际情况来写,我一般以主表条件为主。
HAVING:这个条件字的执行优先级低于on和where,这也就是说明,之后再on和where都执行完成之后才会执行having。
由于having主要用于函数的条件查询,所以速度会很慢的。没有必要,不要使用having,很多用到having的SQL都可以通过子查询查出来。
索引:索引我认为是一个很好的东西和一个很麻烦的东西,建好索引查询速度非常快,建的不好就会严重影响数据库的DML效率和耗费系统资源。
我也没有深入研究过,这里只说一下,我平时写SQL的索引心得。
建立索引:
- 1、不会再中文、超长字符的字段上建立索引;
- 2、尽量建立复合索引;
- 3、在唯一性字段上建立索引,包括复合型;
- 4、不会再条件查询以外的字段上建立索引,也就是where和on后面的条件字段上建立索引。
- 5、尽可能少的建立索引,例如,t1表有idx01=col1索引和idx02=col1、col2两个索引,那么idx01这个索引没有必要建立。
索引使用:
- 1、复合索引是有序的
例如:索引idx0001 = col1 , col2 , col3 三个字段,那么和idx0002 = col2 , col1 , col3是两个不同的索引。在查询的时候如果where和on中只用到了col1的话,那么idx0001索引会生效,idx0002则不生效,
- 2、在where和on的后面索引字段上不要用函数这样索引会失效
例如:select col1 , col2 from t1 where rtrim(t1.col1) = ‘a’ 这种写法是不可取的select col1 , col2 from t1 where t1.col1 = lpad(‘a’,10,’ ‘);换成这种写法。
- 3、在编写SQL的时候要看一下,涉及到表中已经存在索引,最好使用现有的索引来编写SQL。
就写这么写吧,我写的不一定对,只是分享一下我个人心得,以后有新的体会还在于大家分享。