优化SQL Server数据库查询方法(2)

发表于:2014-03-10来源:IT专家网作者:不详点击数: 标签:SQL Server
每个数据库都有一个全局当前时间戳值:@@DBTS。每次以任何方式更改带有timestamp 列的行时,SQL Server 先在时间戳列中存储当前的 @@DBTS 值,然后增加 @@DBT

  每个数据库都有一个全局当前时间戳值:@@DBTS。每次以任何方式更改带有timestamp 列的行时,SQL Server 先在时间戳列中存储当前的 @@DBTS 值,然后增加 @@DBTS 的值。如果某个表具有timestamp 列,则时间戳会被记到行级。服务器就可以比较某行的当前时间戳值和上次提取时所存储的时间戳值,从而确定该行是否已更新。服务器不必比较所有列的值,只需比较 timestamp 列即可。如果应用程序对没有timestamp 列的表要求基于行版本控制的乐观并发,则游标默认为基于数值的乐观并发控制。SCROLL LOCKS 这个选项实现悲观并发控制。在悲观并发控制中,在把数据库的行读入游标结果集时,应用程序将试图锁定数据库行。在使用服务器游标时,将行读入游标时会在其上放置一个更新锁。如果在事务内打开游标,则该事务更新锁将一直保持到事务被提交或回滚;当提取下一行时,将除去游标锁。如果在事务外打开游标,则提取下一行时,锁就被丢弃。

  因此,每当用户需要完全的悲观并发控制时,游标都应在事务内打开。更新锁将阻止任何其它任务获取更新锁或排它锁,从而阻止其它任务更新该行。然而,更新锁并不阻止共享锁,所以它不会阻止其它任务读取行,除非第二个任务也在要求带更新锁的读取。滚动锁根据在游标定义的语句中指定的锁提示,这些游标并发选项可以生成滚动锁。滚动锁在提取时在每行上获取,并保持到下次提取或者游标关闭,以先发生者为准。下次提取时,服务器为新提取中的行获取滚动锁,并释放上次提取中行的滚动锁。滚动锁独立于事务锁,并可以保持到一个提交或回滚操作之后。如果提交时关闭游标的选项为关,则COMMIT语句并不关闭任何打开的游标,而且滚动锁被保留到提交之后,以维护对所提取数据的隔离。所获取滚动锁的类型取决于游标并发选项和游标 语句中的锁提示。锁提示 只读乐观数值指定 NOLOCK 提示将使指定了该提示的表在游标内是只读的。

  16、用Profiler来跟踪查询,得到查询所需的时间,找出SQL的问题所在;用索引优化器优化索引17、注意UNion和UNion all 的区别。UNION all好18、注意使用DISTINCT,在没有必要时不要用,它同UNION一样会使查询变慢。重复的记录在查询里是没有问题的19、查询时不要返回不需要的行、列

  20、用sp_configure ''query governcost limit''或者SET QUERY_GOVERNOR_COST_LIMIT来限制查询消耗的资源。当评估查询消耗的资源超出限制时,服务器自动取消查询,在查询之前就扼杀掉。SET LOCKTIME设置锁的时间21、用top 100 / 10 Percent 来限制用户返回的行数或者SET ROWCOUNT来限制操作的行22、在SQL2000以前,一般不要用如下的字句: "IS NULL", "<>", "!=", "!>", "!<", "NOT", "NOT EXISTS", "NOT IN", "NOT LIKE", "LIKE ''%500''",因为他们不走索引全是表扫描。也不要在WHere字句中的列名加函数,如Convert,substring等,如果必须用函数的时候,创建计算列再创建索引来替代。还可以变通写法:WHERE SUBSTRING(firstname,1,1) = ''m''改为WHERE firstname like ''m%''(索引扫描),一定要将函数和列名分开。并且索引不能建得太多和太大。NOT IN会多次扫描表,使用EXISTS、NOT EXISTS ,IN , LEFT OUTER 来替代,特别是左连接,而Exists比IN更快,最慢的是NOT操作。如果列的值含有空,以前它的索引不起作用,现在2000的优化器能够处理了。相同 的是IS NULL,“NOT", "NOT EXISTS", "NOT IN"能优化她,而”<>”等还是不能优化,用不到索引。

  23、使用Query Analyzer,查看SQL语句的查询计划和评估分析是否是优化的SQL。一般的20%的代码占据了80%的资源,我们优化的重点是这些慢的地方。

  24、如果使用了IN或者OR等时发现查询没有走索引,使用显示申明指定索引:* FROM PersonMember (INDEX = IX_Title) WHERE processid IN (‘男’,‘女’)25、将需要查询的结果预先计算好放在表中,查询的时候再SELECT。这在SQL7.0以前是最重要的手段。例如医院的住院费计算。

  26、MIN()和MAX()能使用到合适的索引。

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

  28、如果要插入大的二进制值到Image列,使用存储过程,千万不要用内嵌INsert来插入(不知JAVA 是否)。因为这样应用程序首先将二进制值转换成字符串(尺寸是它的两倍),服务器受到字符后又将他转换成二进制值存储过程就没有这些动作,方法:Create procedure p_as into table(Fimage) values (@image), 在前台调用这个存储过程传入二进制参数,这样处理速度明显改善。

原文转自:http://database.ctocio.com.cn/422/12734922.shtml