1、在查询中不要使用“select *”
(1)检索不必要的列会带来额外的系统开销,有句话叫做“该省的则省”;
(2)数据库不能利用“覆盖索引”的优点,因此查询缓慢。
2、在select清单中避免不必要的列,在连接条件中避免不必要的表
(1)在select查询中如有不必要的列,会带来额外的系统开销,特别是LOB类型的列;
(2)在连接条件中包含不必要的表会强制数据库引擎检索和匹配不需要的数据,增加了查询执行时间。
3、不要在子查询中使用count()求和执行存在性检查
(1)不要使用 SELECT column_list FROM table WHERE0< (SELECT count(*) FROM table2 WHERE ..)
使用 SELECT column_list FROM table WHERE EXISTS (SELECT * FROM table2 WHERE ...) 代替;
(2)当你使用count()时,SQL Server不知道你要做的是存在性检查,它会计算所有匹配的值,要么会执行全表扫描,要么会扫描最小的非聚集索引;
(3)当你使用EXISTS时,SQL Server知道你要执行存在性检查,当它发现第一个匹配的值时,就会返回TRUE,并停止查询。类似的应用还有使用IN或ANY代替count()。
4、避免使用两个不同类型的列进行表的连接
(1)当连接两个不同类型的列时,其中一个列必须转换成另一个列的类型,级别低的会被转换成高级别的类型,转换操作会消耗一定的系统资源;
(2)如果你使用两个不同类型的列来连接表,其中一个列原本可以使用索引,但经过转换后,优化器就不会使用它的索引了。例如:
在这个例子中,SQL Server会将int列转换为float类型,因为int比float类型的级别低,large_table.int_column上的索引就不会被使用,但smalltable.float_column上的索引可以正常使用。
5、避免死锁
(1)在你的存储过程和触发器中访问同一个表时总是以相同的顺序;
(2)事务应经可能地缩短,在一个事务中应尽可能减少涉及到的数据量;
(3)永远不要在事务中等待用户输入。
6、使用“基于规则的方法”而不是使用“程序化方法”编写TSQL
(1)数据库引擎专门为基于规则的SQL进行了优化,因此处理大型结果集时应尽量避免使用程序化的方法(使用游标或UDF[User Defined Functions]处理返回的结果集) ;
(2)如何摆脱程序化的SQL呢?有以下方法:
- 使用内联子查询替换用户定义函数;
- 使用相关联的子查询替换基于游标的代码;
- 如果确实需要程序化代码,至少应该使用表变量代替游标导航和处理结果集。
7、避免使用count(*)获得表的记录数
(1)为了获得表中的记录数,我们通常使用下面的SQL语句: SELECT COUNT(*) FROM dbo.orders
这条语句会执行全表扫描才能获得行数。
(2)但下面的SQL语句不会执行全表扫描一样可以获得行数:
8、避免使用动态SQL
除非迫不得已,应尽量避免使用动态SQL,因为:
(1)动态SQL难以调试和故障诊断;
(2)如果用户向动态SQL提供了输入,那么可能存在SQL注入风险。
9、避免使用临时表
(1)除非却有需要,否则应尽量避免使用临时表,相反,可以使用表变量代替;
(2)大多数时候(99%),表变量驻扎在内存中,因此速度比临时表更快,临时表驻扎在TempDb数据库中,因此临时表上的操作需要跨数据库通信,速度自然慢。
10、使用全文搜索搜索文本数据,取代like搜索
全文搜索始终优于like搜索:
(1)全文搜索让你可以实现like不能完成的复杂搜索,如搜索一个单词或一个短语,搜索一个与另一个单词或短语相近的单词或短语,或者是搜索同义词;
(2)实现全文搜索比实现like搜索更容易(特别是复杂的搜索);
不了解全文搜索的可以查看https://www.cnblogs.com/ljhdo/p/5041605.html
11、使用union实现or操作
(1)在查询中尽量不要使用or,使用union合并两个不同的查询结果集,这样查询性能会更好;
(2)如果不是必须要不同的结果集,使用union all效果会更好,因为它不会对结果集排序。
UNION和UNION ALL的作用和语法
UNION 用于合并两个或多个 SELECT 语句的结果集,并消去表中任何重复行。
UNION 内部的 SELECT 语句必须拥有相同数量的列,列也必须拥有相似的数据类型。
同时,每条 SELECT 语句中的列的顺序必须相同.
SQL UNION 语法:
注释:默认地,UNION 操作符选取不同的值。如果允许重复的值,请使用 UNION ALL。
当 ALL 随 UNION 一起使用时(即 UNION ALL),不消除重复行
SQL UNION ALL 语法
12、为大对象使用延迟加载策略
(1)在不同的表中存储大对象(如VARCHAR(MAX),Image,Text等),然后在主表中存储这些大对象的引用;
(2)在查询中检索所有主表数据,如果需要载入大对象,按需从大对象表中检索大对象。
13、使用VARCHAR(MAX),VARBINARY(MAX) 和 NVARCHAR(MAX)
(1)在SQL Server 2000中,一行的大小不能超过800字节,这是受SQL Server内部页面大小8KB的限制造成的,为了在单列中存储更多的数据,你需要使用TEXT,NTEXT或IMAGE数据类型(BLOB);
(2)这些和存储在相同表中的其它数据不一样,这些页面以B-Tree结构排列,这些数据不能作为存储过程或函数中的变量,也不能用于字符串函数,如REPLACE,CHARINDEX或SUBSTRING,大多数时候你必须使用READTEXT,WRITETEXT和UPDATETEXT;
(3)为了解决这个问题,在SQL Server 2005中增加了VARCHAR(MAX),VARBINARY(MAX) 和 NVARCHAR(MAX),这些数据类型可以容纳和BLOB相同数量的数据(2GB),和其它数据类型使用相同的数据页;
(4)当MAX数据类型中的数据超过8KB时,使用溢出页(在ROW_OVERFLOW分配单元中)指向源数据页,源数据页仍然在IN_ROW分配单元中。
14、在用户定义函数中使用下列最佳实践
不要在你的存储过程,触发器,函数和批处理中重复调用函数,例如,在许多时候,你需要获得字符串变量的长度,无论如何都不要重复调用LEN函数,只调用一次即可,将结果存储在一个变量中,以后就可以直接使用了。
15、在存储过程中使用下列最佳实践
(1)不要使用SP_xxx作为命名约定,它会导致额外的搜索,增加I/O(因为系统存储过程的名字就是以SP_开头的),同时这么做还会增加与系统存储过程名称冲突的几率;
(2)将Nocount设置为On避免额外的网络开销;
(3)当索引结构发生变化时,在EXECUTE语句中(第一次)使用WITH RECOMPILE子句,以便存储过程可以利用最新创建的索引;
(4)使用默认的参数值更易于调试。
16、在触发器中使用下列最佳实践
(1)最好不要使用触发器,触发一个触发器,执行一个触发器事件本身就是一个耗费资源的过程;
(2)如果能够使用约束实现的,尽量不要使用触发器;
(3)不要为不同的触发事件(Insert,Update和Delete)使用相同的触发器;
(4)不要在触发器中使用事务型代码。
17、在视图中使用下列最佳实践
(1)为重新使用复杂的TSQL块使用视图,并开启索引视图;
(2)如果你不想让用户意外修改表结构,使用视图时加上SCHEMABINDING选项;
(3)如果只从单个表中检索数据,就不需要使用视图了,如果在这种情况下使用视图反倒会增加系统开销,一般视图会涉及多个表时才有用。
18、在事务中使用下列最佳实践
(1)SQL Server 2005之前,在BEGIN TRANSACTION之后,每个子查询修改语句时,必须检查@@ERROR的值,如果值不等于0,那么最后的语句可能会导致一个错误,如果发生任何错误,事务必须回滚。从SQL Server 2005开始,Try..Catch..代码块可以处理TSQL中的事务,因此在事务型代码中最好加上Try…Catch…;
(2)避免使用嵌套事务,使用@@TRANCOUNT变量检查事务是否需要启动(为了避免嵌套事务);
(3)尽可能晚启动事务,提交和回滚事务要尽可能快,以减少资源锁定时间。
19、应用正确的索引(索引是个大主题,后面会单独写一篇)
(注:本文来源于摘抄,因为文章不错,又担心有天链接出问题,所以就复制借鉴了,因此如有雷同,不属巧合!!!)
原文:https://www.cnblogs.com/ZhangQi-BoKe/p/14389779.html