SQL优化

Posted xiaoxiaoqiao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SQL优化相关的知识,希望对你有一定的参考价值。

当数据量达到一定大小,SQL优化显得尤为重要,然而庞大的SQL语句造成优化困难,如何在平时避免影响效率的写法

一、查询速度慢的原因很多,常见如下几种       

     a、没有索引或者没有用到索引(这是查询慢最常见的问题,是程序设计的缺陷。建表时一定记得建索引,当数据量很大以后建索引的速度很慢,
          且建的过程中影响对数据的其 他操作)      

     b、查询出的数据量过大(可以采用多次查询,分页查询其他的方法降低数据量)

     c、锁或者死锁(这也是查询慢最常见的问题,是程序设计的缺陷) 
     d、sp_lock,sp_who,活动的用户查看,原因是读写竞争资源。 
     e、返回了不必要的行和列 
     f、查询语句不好,没有优化
     g、I/O吞吐量小,形成了瓶颈效应。 
     h、没有创建计算列导致查询不优化。 (指某个特定的数据根据算法得来,给这个数据单独建字段自动计算,这个平时并未用到)
     i、内存不足 
     j、网络速度慢 

二、可通过如下方法提高效率(注意观察执行计划)

总体:根据查询条件,建立索引,优化索引、优化访问方式,限制结果集的数据量。注意填充因子要适当(最好是使用默认值0)。

索引方面:

(1)、索引应该尽量小,使用字节数小的列建索引好(参照索引的创建)

(2)、不要对有限的几个值的字段建单一索引如性别字段 。

(3)、组合索引,两个或多个字段用一个索引,这种索引用在经常需要这两个字段一起查询数据的情况,也可以建组合索引后再建单列索引,查询时会优先组合索引。例如:select * from users where area=’beijing’ and age=22;  area 和age可以建一个组合索引速度快。因为索引也需要大量资源空间,一个索引比两个索引快。

其他:

(1)、字段不要有NULL值。查询条件IS  not null  和 IS  NULL 这种不参与索引查询,

(2)、如果使用了IN或者OR等时发现查询没有走索引,使用强制索引:   SELECT   *   FROM   PersonMember   WITH(NOLOCK,INDEX   =   IX_Title)   WHERE   processid   IN   (‘男’,‘女’)

       用OR的字句可以分解成多个查询,并且通过UNION   连接多个查询。他们的速度只同是否使用索引有关,如果查询需要用到联合索引,用UNION   all执行的效率更高.多个OR的字句没有用到索引,改写成              UNION的形式再试图与索引匹配。一个关键的问题是否用到索引。

(3)、如果是使用like进行查询的话,简单的使用index是不行的,但是全文索引,耗空间。   like   ‘a%‘   使用索引   like   ‘%a‘   不使用索引用   like   ‘%a%‘   查询时,查询耗时和字段值总长度成正比,所以不能用CHAR类型,而是VARCHAR。对于字段的值很长的建全文索引。 

(4)、在查询Select语句中用Where字句限制返回的行数,避免表扫描,如果返回不必要的数据,浪费了服务器的I/O资源,加重了网络的负担降低性能。如果表很大,在表扫描的期间将表锁住,禁止其他的联接访问表,后果严重(这个问题加WITN(NOLOCK)可解决,但是会造成脏读,可以了解下)。

(5)、在SQL2000以前,一般不要用如下的字句:   "IS   NULL",   " <> ",   "!=",   "!> ",   "! <",   "NOT",   "NOT   EXISTS",   "NOT   IN",   "NOT   LIKE",   and   "LIKE   ‘%500‘",因为他们不走索引全是表扫描。NOT   IN会多次扫描表,使用EXISTS、NOT   EXISTS   ,IN   ,   LEFT   OUTER   JOIN   来替代,特别是左连接,而Exists比IN更快,最慢的是NOT操作.如果列的值含有空,以前它的索引不起作用,现在2000的优化器能够处理了。相同的是IS   NULL,“NOT",   "NOT   EXISTS",   "NOT   IN"能优化她,而” <> ”等还是不能优化,用不到索引。

     --低效率写法: IF (SELECT COUNT(*) FROM table_name WHERE column_name = ‘xxx‘)     

      --正确的写法: IF EXISTS (SELECT * FROM table_name WHERE column_name = ‘xxx‘)

(6)、不要在Where字句中的列名加函数,如Convert,substring等,如果必须用函数的时候,创建计算列再创建索引来替代.还可以变通写法:WHERE   SUBSTRING(firstname,1,1)   =   ‘m‘改为WHERE   firstname   like   ‘m%‘(索引扫描),一定要将函数和列名分开。并且索引不能建得太多和太大。--计算列没用过也没校验过

(7)、注意UNionUNion   all   的区别。UNION   all好

(8)、注意使用DISTINCT,在没有必要时不要用,它同UNION一样会使查询变慢。重复的记录在查询里是没有问题的

(9)、查询时不要返回不需要的行、列

(10)、Between在某些时候比IN速度更快,Between能够更快地根据索引找到范围。用查询优化器可见到差别。   select  *   from   chineseresume   where   title   in   (‘男‘,‘女‘)   Select   *   from   chineseresume   where   between   ‘男‘   and   ‘女‘   结果是一样的。由于in会在比较多次,所以有时会慢些。

(11)、尽量少用视图,它的效率低。对视图操作比直接对表操作慢,可以用stored   procedure来代替她。特别的是不要用视图嵌套,嵌套视图增加了寻找原始资料的难度。我们看视图的本质:它是存放在服务器上的被优化好了的已经产生了查询规划的SQL。对单个表检索数据时,不要使用指向多个表的视图,直接从表检索或者仅仅包含这个表的视图上读,否则增加了不必要的开销,查询受到干扰.为了加快视图的查询,MsSQL增加了视图索引的功能。也可将视图中的数据放到临时表中再对临时表进行查询,因临时表存在服务器内存中效率会有所提高,但是数据量大时可能会有反效果。

(12)、一次更新多条记录比分多次更新每次一条快,就是说批处理

(13)、尽量将数据的处理工作放在服务器上,减少网络传输的开销,如使用存储过程。存储过程是编译好、优化过、并且被组织到一个执行规划里、且存储在数据库中的 SQL语句,是控制流语言的集合,速度当然快。用户自定义函数象光标一样执行的消耗大量的资源,如果返回大的结果采用存储过程

 

 

 

    摘自:https://blog.csdn.net/weiwangchao_/article/details/8964998









以上是关于SQL优化的主要内容,如果未能解决你的问题,请参考以下文章

SQL 优化

项目中优化sql语句执行效率的方法是啥?

SQL优化之语句优化

数据库优化篇—— SQL语句优化建议

基于MySQL 的 SQL 优化总结

【DB2】SQL优化