sql优化总结

    技术2022-05-19  21

    为了是自己对sql优化有更好的原则性,在这里做一下总结,个人原则如有不对请多多指教。谢谢!

     

    要知道一个简单的sql语句执行效率,就要有查看方式,一遍更好的进行优化。

     

    一、简单的统计语句执行时间

    declare @d datetime   ---定义一个datetime的变量set @d=getdate()   ---获取查询语句开始前的时间select user_id,baby_alias,provice,city,hits from baby   ---执行查询语句select 语句的执行时间=datediff(ms,@d,getdate())  ---使用datediff()函数,计算精确到ms的执行时间

    二、通过系统函数来查看语句具体执行过程,以了解什么位置使语句效率下降了,从而可以知道优化的着重点。

    SET STATISTICS io ONSET STATISTICS time ONgo ---你要测试的sql语句 select  * from babygoSET STATISTICS profile OFFSET STATISTICS io OFFSET STATISTICS time OFF

     

    接下来就要知道sql的优化原则:

    一、建立必要的索引,合理恰当的使用索引可以带来很的收获,每个索引的建立是有资源消耗的,所以要合理的创建索引;建立索引一般规则如下:

        1 表主键、外键必须建立索引。

        2 数据量大的表必须建立索引,一般数据大于500就需要建立索引。

        3 索引应建立在选择性高的字段上。

        4 在where语句经常出现的条件字段上建立索引。

        5 在经常有其他表连接的表字段上建立索引。

        6 频繁操作的表不要建立太多的索引。

        7 索引应建立在小字段上,不要建立在大的文本字段上。

        8 尽量使用但索引代替组合索引。

        9 建立组合索引必须仔细考虑其必要性,从而加以设置。

        10 删除不必要的索引。

    创建聚集索引和非聚集索引

    --排序(聚集索引)create clustered index inx_tablename on tablename(tablename)--创建非聚集索引create nonclustered index inx_tablename on tablename(tablename)--主键alter table tablename add primary key nonclustered--主键且非聚集(  entry_stock_bi,aid)

    二、对索引主列限制使用<> != is (not) null 等条件限制,如果一定要使用就要使用like限制条件。 

       e.g.  select * from tablename where t_name like 'aa%'

     

    三、避免对条件列处理

       任何对列的操作都可能导致全表扫描,这里所谓的操作包括数据库函数、计算表达式等等,查询时要尽可能将操作移至等式的右边,甚至去掉函数。

         e.g.

    select * from tablename where  substrb(CardNo,1,4)='5378'

     

    select * from tablename where  amount/31< 1000

     

    select * from tablename where  to_char(ActionTime,'yyyymmdd')='20110303'

     

    由于where子句中对列的任何操作结果都是在SQL运行时逐行计算得到的,因此它不得不进行表扫描,而没有使用该列上面的索引;如果这些结果在查询编译时就能得到,那么就可以被SQL优化器优化,使用索引,避免表扫描,因此将SQL重写如下:

     

    select * from tablename where CardNo like  '5378%'

     

    select * from tablename where amount  < 1000*31

     

    select * from tablename where ActionTime= to_date ('20110303' ,'yyyymmdd')

     

    当表数据量达到10万条以上时效果是明显的。

     

     

     

    四、避免条件列没有必要的类型转换。

    e.g.  表example1 中的列col1是字符型(char),则以下语句存在类型转换:

     

    select col1,col2 from example1 where col1>10,

     

    应该写为: select col1,col2 from example1 where col1>'10'。

     

     

    五、尽量不适用in 和 or 条件限制 以下是2500条的数据

    e.g.  select * from tablename where tid in ('1','2')(315ms)

            可以将其优化成

            select * from tablename where tid = '1' (6ms)

            select * from tablename where tid = '2' (3ms)

            然后做一个加法,执行速度会快很多

     

    六、尽量不要使用<>避免全表扫描,如果数据是枚举值,且取值范围固定,则修改为"or"方式,最好是想五 将其拆开处理.

     

    七、数据量超过1000条时添加查询的范围,查询效率会有很大提高.

         e.g.  select * from baby where baby_id<2000

     

               应该优化成

               select * from baby where baby_id<2000 and baby_id>0

     

    八、like子句尽量使用前端匹配,因为在查询中会频繁使用,所以对所选字段建立索引会很好的提高效率。

          e.g.  select * from userdiary where diary_name like '%北%' 

             这里应该优化成

                select * from userdiary where diary_name like '北%'

    这样处理后会有很好的收获。

     

    九、用case语句合并表的多次扫描。

        e.g.

           select count(*) from hitcount where id<100

           select count(*) from hitcount where id between 100 and 500

           select count(*) from hitcount where id >500

     

           将其优化成下面这样

           select count ( case when id<100 then 1 else null end)  count1,       count (case when id between 100 and 500 then 1 else null end) count2,       count (case when id >500 then 1 else null end) count3 from hitcount;

     

    十、使用基于函数的索引

         

    e.g.

     

    select * from baby where substr(ename,1,2)=’SM’;

     

    但是这种查询在客服系统又经常使用,我们可以创建一个带有substr函数的基于函数的索引,

     

    create index baby_ename_substr on baby( substr(ename,1,2) );

     

    这样在执行上面的查询语句时,这个基于函数的索引将排上用场,执行计划将是(INDEX RANGE SCAN)。

     


    最新回复(0)