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)、注意UNion和UNion 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优化的主要内容,如果未能解决你的问题,请参考以下文章