SQL开发注意事项


1.查询的模糊匹配
尽量避免在一个复杂查询里面使用?LIKE '%parm1%' ,?百分号会导致相关列的索引无法使用,最好不要用.
2.索引问题
建立索引可以提高查询速度,提高效率,但是不要在建立索引的数据列上进行下列操作:
·避免对索引字段进行计算操作
·避免在索引字段上使用not , < > ,?!=
·避免在索引列上使用IS NULL和IS NOT NULL
·避免在索引列上出现数据类型的转换
·避免在索引列上使用函数
·避免在建立索引的列中使用空值
3.复杂操作
部分UPDATE、SELECT?语句写得很复杂(经常嵌套多级子查询)——可以考虑适当拆成几步,先生成一些临时数据表,再进行关联操作
4.UPDATE
同一个表的修改在一个过程里出现了好几十次,最好是整合成一个UPDATE语句来完成
5.在可以使用UNION ALL的语句里,不要使用UNION
UNION?因为会将各查询子集的记录做比较,故比起UNION ALL?,通常速度都会慢上许多。一般来说,如果使用UNION ALL能满足要求的话,务必使用UNION ALL。还有一种情况大家可能会忽略掉,就是虽然要求几个子集的并集需要过滤掉重复记录,但由于脚本的特殊性,不可能存在重复记录,这时便应该使用UNION ALL,如xx模块的某个查询程序就曾经存在这种情况,见,由于语句的特殊性,在这个脚本中几个子集的记录绝对不可能重复,故可以改用UNION ALL)
6.对WHERE语句的法则
·可以使用?exist?和not exist代替?in和not in
·可以使用表链接代替?exist。Having可以用where代替,如果无法代替可以分两步处理。
SELECT *??FROM ORDERS WHERE CUSTOMER_NAME NOT IN (SELECT CUSTOMER_NAME FROM CUSTOMER)可改为:
SELECT *??FROM ORDERS WHERE CUSTOMER_NAME not exist (SELECT CUSTOMER_NAME FROM CUSTOMER)
·不要以字符格式声明数字,要以数字格式声明字符值,日期同样,否则会使索引无效,产生全表扫描
SELECT NAME FROM TABLE WHERE NO=’123’改为:
SELECT NAME FROM TABLE WHERE NO=123

7.对SELECT语句的法则
在程序、过程、函数等代码中,限制使用?SELECT * FROM TABLE ,即限制使用?*
例外?: 1.提取的字段數量?>=表字段數量?50%?的?就不用改了?.
      2.就是原本?該表字段?數量就不多的.
8.排序避免使用耗费资源的操作,带有DISTINCT,UNION,MINUS,INTERSECT,ORDER BY的SQL语句会启动SQL引擎 执行,耗费资源的排序(SORT)功能. DISTINCT需要一次排序操作, 而其他的至少需要执行两次排序
9.临时表使用临时表可以极大的提高系统的性能
10.查询出的数据量过大(可以采用多次查询,其他的方法降低数据量)
11.锁或者死锁尽量要少使用,他们是查询变慢的最商检原因.
12.Commit和rollback的区别?Rollback:回滚所有的事物。?Commit:提交当前的事物.?没有必要在动态SQL里写事物,如果要写请写在外面如:?begin tran exec(@s) commit trans?或者将动态SQL?写成函数或者存储过程。

13.在查询Select语句中用Where字句限制返回的行数,避免表扫描,如果返回不必要的数据,浪费了服务器的I/O资源,加重了网络的负担降低性能。如果表很大,在表扫描的期间将表锁住,禁止其他的联接访问表,后果严重。

14.SQL的注释申明对执行没有任何影响

15.注意UNion和UNion all?的区别。UNION all好

16.注意使用DISTINCT,在没有必要时不要用,它同UNION一样会使查询变慢。重复的记录在查询里是没有问题的,可以用EXISTS替换DISTINCT

17.用select top 100 / 10 Percent?来限制用户返回的行数或者SET ROWCOUNT来限制操作的行

18.如果使用了IN或者OR等时发现查询没有走索引,使用显示申明指定索引:?Select * FROM PersonMember (INDEX = IX_Title) Where processid IN ('男','女')

19.可以用in来代替or,例如?SELECT NO WHERE NO=1 OR NO=2?改为:WHERE NO IN(1,2)

20.MIN()?和?MAX()能使用到合适的索引。

21.数据库有一个原则是代码离数据越近越好,所以优先选择Default,依次为Rules,Triggers, Constraint(约束如外健主健CheckUNIQUE……,数据类型的最大长度等等都是约束),Procedure.这样不仅维护工作小,编写程序质量高,并且执行的速度快。

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

23.不要建没有作用的事物,例如产生报表时,浪费资源。只有在必要使用事物时使用它。

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

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

26.没有必要时不要用DISTINCT和ORDER BY,这些动作可以改在客户端执行。它们增加了额外的开销。这同UNION?和UNION ALL一样的道理。

27.在IN后面值的列表中,将出现最频繁的值放在最前面,出现得最少的放在最后面,减少判断的次数。

28.当用Select INTO时,它会锁住系统表(sysobjects,sysindexes等等),阻塞其他的连接的存取。创建临时表时用显示申明语句,而不是?select INTO. drop table t_lxh begin tran select * into t_lxh from chineseresume where name = 'XYZ' --commit?在另一个连接中Select * from sysobjects可以看到?Select INTO?会锁住系统表,Create table?也会锁系统表(不管是临时表还是系统表)。所以千万不要在事物内使用它!!!这样的话如果是经常要用的临时表请使用实表,或者临时表变量。

29.一般在GROUP BY?和HAVING字句之前就能剔除多余的行,所以尽量不要用它们来做剔除行的工作。他们的执行顺序应该如下最优:select的Where字句选择所有合适的行,Group By用来分组个统计行,Having字句用来剔除多余的分组。这样Group By?个Having的开销小,查询快.对于大的数据行进行分组和Having十分消耗资源。如果Group BY的目的不包括计算,只是分组,那么用Distinct更快

30.一次更新多条记录比分多次更新每次一条快,就是说批处理好

31.少用临时表,尽量用结果集和Table类性的变量来代替它,Table?类型的变量比临时表好

32.尽量将数据的处理工作放在服务器上,减少网络的开销,如使用存储过程。存储过程是编译好、优化过、并且被组织到一个执行规划里、且存储在数据库中的SQL语句,是控制流语言的集合,速度当然快。反复执行的动态SQL,可以使用临时存储过程,该过程(临时表)被放在Tempdb中。以前由于SQL SERVER对复杂的数学计算不支持,所以不得不将这个工作放在其他的层上而增加网络的开销。SQL2000支持UDFs,现在支持复杂的数学计算,函数的返回值不要太大,这样的开销很大。用户自定义函数象光标一样执行的消耗大量的资源,如果返回大的结果采用存储过程

33.不要在一句话里再三的使用相同的函数,浪费资源,将结果放在变量里再调用更快

34.Select COUNT(*)的效率教低,尽量变通其他的写法,而EXISTS快.同时请注意区别:?select count(Field of null) from Table?和?select count(Field of NOT null) from Table?的返回值是不同的

35.当服务器的内存够多时,配制线程数量?=?最大连接数+5,这样能发挥最大的效率;否则使用?配制线程数量<最大连接数启用SQL SERVER的线程池来解决,如果还是数量?=?最大连接数+5,严重的损害服务器的性能。

36.按照一定的次序来访问你的表。如果你先锁住表A,再锁住表B,那么在所有的存储过程中都要按照这个顺序来锁定它们。如果你(不经意的)某个存储过程中先锁定表B,再锁定表A,这可能就会导致一个死锁。如果锁定顺序没有被预先详细的设计好,死锁很难被发现

37.尽量避免大事务操作,慎用holdlock子句,提高系统并发能力。

38.尽量避免反复访问同一张或几张表,尤其是数据量较大的表,可以考虑先根据条件提取数据到临时表中,然后再做连接。

39.尽量避免使用游标,因为游标的效率较差,如果游标操作的数据超过1万行,那么就应该改写;如果使用了游标,就要尽量避免在游标循环中再进行表连接的操作

40.注意where字句写法,必须考虑语句顺序,应该根据索引顺序、范围大小来确定条件子句的前后顺序,尽可能的让字段顺序与索引顺序相一致,范围从大到小。

41.不要在where子句中的“=”左边进行函数、算术运算或其他表达式运算,否则系统将可能无法正确使用索引。

42.尽量使用exists代替select count(1)来判断是否存在记录,count函数只有在统计表中所有行数时使用,而且count(1)比count(*)更有效率。

43.尽量使用“>=”,不要使用“>”。

44.注意insert、update操作的数据量,防止与其他应用冲突。如果数据量超过200个数据页面(400k),那么系统将会进行锁升级,页级锁会升级成表级锁。? 

45.尽可能的使用索引字段作为查询条件,尤其是聚簇索引,必要时可以通过index index_name来强制指定索引

46.??用TRUNCATE替代DELETE:当删除表中的记录时,在通常情况下,?回滚段(rollback segments )?用来存放可以被恢复的信息.?如果你没有COMMIT事务,ORACLE会将数据恢复到删除之前的状态(准确地说是恢复到执行删除命令之前的状况)?而当运用TRUNCATE时,?回滚段不再存放任何可被恢复的信息.当命令运行后,数据不能被恢复.因此很少的资源被调用,执行时间也会很短. (译者按: TRUNCATE只在删除全表适用,TRUNCATE是DDL不是DML)

47.在使用索引字段作为条件时,如果该索引是联合索引,那么必须使用到该索引中的第一个字段作为条件时才能保证系统使用该索引,否则该索引将不会被使用。
48.尽量避免使用distinct、order by、group by、having、join、cumpute,因为这些语句会加重tempdb的负担。

49.如果索引是建立在多个列上,?只有在它的第一个列(leading column)被where子句引用时,优化器才会选择使用该索引.?这也是一条简单而重要的规则,当仅引用索引的第二个列时,优化器使用了全表扫描而忽略了索引

50.所有的select 語句必須加 with nolock,例如:
SELECT COUNT(UserID) FROM table WITH (NOLOCK) ……

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值