技术开发 频道

十步优化SQL Server中的数据访问

  第五步:识别低效TSQL,采用非常好的实践重构和应用TSQL

  由于每个程序员的能力和习惯都不一样,他们编写的TSQL可能风格各异,部分代码可能不是非常好的实现,对于水平一般的程序员可能首先想到的是编写TSQL实现需求,至于性能问题日后再说,因此在开发和测试时可能发现不了问题。

  也有一些人知道非常好的实践,但在编写代码时由于种种原因没有采用非常好的实践,等到用户发飙的那天才乖乖地重新埋头思考非常好的实践。

  我觉得还是有必要介绍一下具有都有哪些非常好的实践。

  1、在查询中不要使用“select *”

  (1)检索不必要的列会带来额外的系统开销,有句话叫做“该省的则省”;

  (2)数据库不能利用“覆盖索引”的优点,因此查询缓慢。

  2、在select清单中避免不必要的列,在连接条件中避免不必要的表

  (1)在select查询中如有不必要的列,会带来额外的系统开销,特别是LOB类型的列;

  (2)在连接条件中包含不必要的表会强制数据库引擎检索和匹配不需要的数据,增加了查询执行时间。

  3、不要在子查询中使用count()求和执行存在性检查

  (1)不要使用

SELECT column_list FROM table WHERE 0 < (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)如果你使用两个不同类型的列来连接表,其中一个列原本可以使用索引,但经过转换后,优化器就不会使用它的索引了。例如: 

SELECT column_list FROM small_table, large_table WHERE

  smalltable.float_column
= large_table.int_column

  在这个例子中,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呢?有以下方法:

  - 使用内联子查询替换用户定义函数;

  - 使用相关联的子查询替换基于游标的代码;

  - 如果确实需要程序化代码,至少应该使用表变量代替游标导航和处理结果集。

2
相关文章