翻译:改进.NET应用程序的性能和可伸缩性(四)-SQL Server性能
摘要:本来是想把SQL Server性能这节分两篇发出来的,但为了完整还是整成一篇发出来吧,从执行计划一节到最后是今天翻的。红色标注的是拿不准的地方,不对的地方大家指正。对于英文差的同学,阅读英文资料是个痛苦的过程,但通过阅读,让我更深入的了解了SQL Server。
向上扩容和平面扩容
Optimize the application before scaling up or scaling out.
在你进行向上扩容和平面扩容前优化你的应用。
译注:你可以减少无效的锁,使用参数化查询,增加合适的索引等操作来提高磁盘,内存和CPU的利用率。
Address historical and reporting data.
处理历史和用于报表的数据。
译注:一个运行时间很长的系统肯定有很多历史数据,在现网库里一直保存这些数据,肯定会给线上的应用带来负面影响,查询一个小库和查询一个大库的开销差别很大,所以一般应该把历史数据的一部分分到不同的区里,历史数据是只读的,甚至可以放到另外的只读数据库里。用于报表的数据也是,大多都是历史数据,可以建立单独的数据仓库去存放他们,不要和现网库放在一起。
Scale up for most applications.
对大多数应用进行向上扩容。
译注:如果你在处理了历史数据和报表数据后还有更好的硬件,那就先添加这些新的硬件,比如更快的CPU和硬盘,更大的内存等,但添加了新的硬件后记着修改你的SQLSERVER的配置以适应这些新硬件,比如要打开/3G开关以使用更多的内存。
Scale out when scaling up does not suffice or is cost-prohibitive.
在你向上扩容仍不满足或者向上扩容成本太高的时候使用横向扩容。
译注:横向扩容的时候可能需要对一些表进行水平分区,使这些分区到不同的机器上,而这种办法可能需要在多台机器间用SQLSERVER的复制功能复制数据。而且使用大量的PC server做成的联合服务器在在灾后恢复和容灾上也更加复杂,你需要权衡引入这些复杂性和花钱买硬件哪个更值得。
Schema
Devote the appropriate resources to schema design.
给予适当的资源用来进行schema设计。
译注:在进行架构设计前一定要花费足够的时间和投入足够的资源来进行业务逻辑收集,设计及测试数据模型,如果上线之后再修改数据模型代价将非常高。
Separate online analytical processing (OLAP) and online transaction processing (OLTP) workloads.
分割OLAP和OLTP负载。
译注:OLAP的特点是经常执行一些长时间的查询,OLTP的特点是都是小而多的事务,一般在1秒中就得返回,长时间运行的查询分析,报表查询和即席查询会阻碍插入和其它OLTP的事务。如果需要同时支持两种类型的工作,考虑创建一个报表服务器来支持OLAP和报表,可以使用SSAS来支持这些工作。
Normalize first, denormalize later for performance.
先遵守范式设计数据库,然后再不遵守范式来优化性能。
译注:遵循范式设计数据库可以让数据库减少冗余,但写出来的查询语句却很复杂,带有很多join等,而且会降低性能,有时候为了防止一些常用的查询跨表查询,会在多个表里存放相同的数据,以提高性能,但这违反了范式。
Define all primary keys and foreign key relationships.
确定所有的主键和外键关系。
译注:选择合适的主键和外键关系会很大程度上影响查询计划的生成,从而影响性能。另外可考虑使用声明性引用完整性 (DRI) ,设置好主外键和DRI的情况下,更新主表会自动修改子表,级联更新和级联删除等,而且性能比触发器要好。
Define all unique constraints and check constraints.
确定所有的唯一索引和约束。
译注:唯一索引和检查约束为查询计划提供了更多的信息,比如你做了一个id列不等于0的约束,如果你一个查询语句查询id=0的数据,就不用扫描任何数据表,只检查约束就可以了。
Choose the most appropriate data type.
选择最适合的数据类型。
译注:尽量选用比较窄的类型,能用smallint不用int,选择合适的类型,避免类型转换,需要类型转换的查询语句有可能不能有效利用索引;避免外键列允许为空[不确定];能用varchar的地方不要用Text字段,Text字段性能不行;尽量少使用sql_variant,虽然灵活,但使用它会带来更多的类型转换而降低性能;因为win2000和.net里的字符串都是unicode的,所以尽量使用nchar和nvarchar,虽然它比较占空间,但像存储电话号码和邮件等用varchar和char就行了[该条可能有争议,我不确认]。
Use indexed views for denormalization.
为不遵守范式的表使用索引视图。
译注:当你需要join几个不常变化的表来查询,像查找表等,可以为他们建立一个视图索引,视图索引像表一样是物理存在的,能提高性能。
Partition tables vertically and horizontally.
垂直或者水平分割表。
译注:可以把表垂直分割,把不常访问的列划分到别的表里,以便一个页里可以保存更多的行;水平分割稍微复杂一点,但会带来更大的灵活性,常见的做法是利用时间字段把历史数据和存档数据进行水平分割,然后使用检查约束和分区视图把他们联合起来;数据依赖路由(Data-dependent routing )是一个强大的系统,它可以使用表格来保存分区信息,查询请求会自动路由到相应的分区,从而避免了使用分区视图[没试过这个东西];如果使用分区视图要确保查询计划只访问相关的表,这个要查看利用分区视图的执行计划的详细图表输出。
查询
Know the performance and scalability characteristics of queries.
明确影响性能和可扩展性的查询。
译注:你得衡量和理解最常用的查询,这些查询对性能和可伸缩性影响是最大的。这需要DBA和开发人员的交互来完成,DBA应该经常监控常用的耗费资源的查询来告诉架构师和开发人员,开发人员去编写适当的索引,或者刚开始的时候开发人员编写好查询和索引,提交给DBA,由DBA去优化查询及去除多余的索引。
Write correctly formed queries.
编写正确的form子句。
译注:不必要的表不要join进来;尽量避免使用DISTINCT从句。
Return only the rows and columns needed.
仅仅返回你需要的行和列。
译注:select * 不仅会加大网络流量,而且更容易引起表扫描;使用where语句来限制你返回的行,对大结果集进行分页返回。
Avoid expensive operators such as NOT LIKE.
避免像NOT LIKE等耗费性能的操作。
译注:like后面不要跟前面是通配符的单词;像<>和not like等谓词尽量少用,尽量用IF EXISTS和IF NOT EXISTS来取代,这样可以使用索引。
Avoid explicit or implicit functions in WHERE clauses.
避免在where子句里使用隐式和显示的函数。
译注:不要在列上使用函数,可以在标量上使用函数,如 WHERE DATEADD(day, 15, OrderDate) = '07/23/1996'改成OrderDate = DATEADD(day, -15, '07/23/1996');不要声明一个char变量去和nchar列去比较,相反nvarcha和varchar也一样,在比较的时候会隐式使用Convert函数,进而可能无法使用索引。
Use locking and isolation level hints to minimize locking.
使用锁提示和隔离提示来最小化锁。
译注:要理解下四种事务隔离级别(Read uncommitted,Read committed,Repeatable read,Serializable),3种基本锁(共享锁、更新锁及独占锁)及3种现象(幻影读,幽灵读和重复读)及它们之间的关系。合理的使用锁提示( WITH (NOLOCK) ,WITH (READUNCOMMITTED),with(UPDLOCK),with(TABLOCK)和with(readpast)),以及在一个会话里使用SET TRANSACTION ISOLATION LEVEL命令来改变默认的事务隔离级别。在select语句上使用nolock锁提示可以避免不必要的读锁,从而不会阻塞其它的写语句;在select语句上使用uptlock锁提示可以让锁保持到事务结束,而不是默认上的读锁只保持到读取数据结束,上了更新锁别的事务可以读取数据,但不能获取锁[不清楚更新锁的这个特性会引起死锁还是会解决死锁]。在你批量跟新数据的时候可以使用TABLOCK锁暗示,这比默认上的一大坨细粒度的页锁行锁开销要小很多。
Use stored procedures or parameterized queries.
使用存储过程和参数化查询。
译注:存储过程的好处:逻辑分离,把业务逻辑和数据处理逻辑分离;调整SQL语句不需要重新部署程序;减少网络带宽;提高安全性和集成性,可以给存储过程指派访问权限等[不确定是否可以];参数化查询可以防止SQL注入;防止查询计划重编译。
Minimize cursor use.
最小化游标的使用。
译注:游标的使用会反复提取行,加锁,管理锁,返回行等一系列操作,要用也尽量用只读向前游标,少用火线游标,它们会增加对tempdb的压力[不确定]。通常游标用来处理连续的行,如果这个表有主键,可以用一个wihe语句来取代游标的使用。
Avoid long actions in triggers.
避免在触发器里执行长时间的操作。
译注:触发器里操作会引起新的事务,因为一般在触发器里写的都是update,insert和Delete语句,如果事务过长会影响其它的查询,如果必须要这么做,可以使用消息队列来异步的做。
Use temporary tables and table variables appropriately.
适当的使用临时表和表变量。
译注:如果你需要经常的创建临时表,考虑使用表变量或者真实表。表变量会在存储过程,函数和批结束后自动清理,如果大量的请求使用临时表会引起临时表和系统表的争用。特别大的临时表也是个问题,应该用物理表代替。表变量也会使用到临时表[不确定],所以也不要使用大的表变量,表变量不能参与查询计划的优化,也不能建立索引。对临时表和表变量要进行合理的评估和测试,考虑它对tempdb的影响。
Limit query and index hint use.
最小化查询和索引暗示。
译注:执行计划引擎会根据查询的成本来优化执行计划,查询的成本随着时间会变化,所以硬编码的查询和索引暗示有可能会变得不是最合理。查询暗示有MERGE, HASH, LOOP, 和FORCE ORDER几种,它会为join操作直接选择一个算法。索引提示是强制指定这个查询使用表上的某个索引。一般来说还是让执行计划引擎自己选择最优化的执行计划,如果有问题你再经过仔细测试和考虑再硬编码索引和查询提示。
Fully qualify database objects.
使用数据库对象的完全限定名。
译注:就是说使用Nothwind.dbo.Employee,而不用Employee,这样会名字解析的资源消耗,避免不必要的Schema锁和查询计划重编译。
索引
Create indexes based on use.
只创建需要的基本的索引。
译注:不要在很少访问的表上创建索引,索引会降低写性能,不要在bit或者很宽的列上创建索引。
Keep clustered index keys as small as possible.
使聚集索引的键尽可能的小。
译注:因为非聚集索引会使用聚集索引键来定位数据行,所以尽量让聚集索引键小。
Consider range data for clustered indexes.
确保聚集索引表示数据的一个范围。
译注:当你的where语句里经常有<,>及between等操作符时,在这些列上建立聚集索引,不一定非在主键上建聚集索引才是合适的,常常应建立在时间字段上,如果这个表是个查找表的话,才会在主键上建立聚集索引,因为查找表一般会直接根据主键去定位一个表。
Create an index on all foreign keys.
在所有的外键上创建一个索引。
译注:外键一般用于join操作,加个索引总是有用的。
Create highly selective indexes.
创建高选取度的索引。
译注:不要在bit列上创建索引,选取度的意思就是说该列上的值比较随机均匀分布,如果该列只有少数几种可能的值,访问索引还得再从索引找到数据页,还不如表扫描呢。使用DBCC SHOW_STATISTICS可以查看表的统计信息。
Create a covering index for often-used, high-impact queries.
为最常用和最重要的查询创建覆盖索引。
译注:就是说让查询成为索引覆盖查询,where和select的列都保存在索引里,可以通过查看执行计划来确认是否把最常用的查询优化成了索引覆盖查询,这是提高性能的关键操作。
Use multiple narrow indexes rather than a few wide indexes.
使用多个窄的索引比使用少的比较宽的索引好。
译注:可以为一个表创建多个索引,我们尽量在多个比较窄的列上创建索引,可以灵活使用而且性能也好,不要在太宽的列上建索引;如果要为一个比较宽的列建立索引的话可以使用CHECKSUM函数来创建哈希索引。
Create composite indexes with the most restrictive column first.
在最需要进行限制的列上创建联合索引。
译注:使用联合索引的话,记着要让where语句使用的列在前面,Select的列在后面,因为统计信息只会存储第一个列的信息,执行计划也只会用到第一个字段。
Consider indexes on columns used in WHERE, ORDER BY, GROUP BY, and DISTINCT clauses.
确保索引在where,order by,group by和distinct子句的列上。
译注:主要是一些进行聚合的和限制条件的列上,还有 MAX, MIN等列上。
Remove unused indexes.
移除用不到的索引。
译注:可以用DMV或者SQL Profeler来找出来利用率低的索引,删了它。
Use the Index Tuning Wizard.
使用索引优化向导。
译注:这个工具可以告诉你尽量在什么列上创建索引,它会利用统计信息来给出你建议,你可以用SQL PROFILER抓一些信息给这个工具,让它做出更好的建议。
事务
Avoid long-running transactions.
避免过长的事务。
译注:事务在开始后会锁定资源以防止其他事务执行,所以要保持事务尽量短。可以在应用里开始一个事务,常用的做法是在开始事务前验证数据的有效性,当然在事务里也需要验证数据,但这已经避免了好多可能在事务里回滚的机会。
Avoid transactions that require user input to commit.
避免需要用户输入才能提交的事务。
译注:用户要是不输入就一辈子也结束不了事务了。
Access heavily used data at the end of the transaction.
把访问最不容易使用的数据的代码放在事务的最后。
译注:把选择数据的操作放在事务的开始,更新操作放在后面,可能会引起很大锁争用的语句放在最后,这样可以让锁的时间变的少一些。
Try to access resources in the same order.
使用相同的顺序去访问资源。
译注:防止死锁。
Use isolation level hints to minimize locking.
使用隔离级别提示最小化锁。
译注:常见的就是在Select上使用with(nolock)来取消锁,当然得是在你业务逻辑允许的情况下。
Ensure that explicit transactions commit or roll back.
确保显示的提交事务和回滚。
译注:所有的事务应该有明确的错误处理,在错误的时候回滚事务,如果事务不能完成就会一直锁定资源。可以使用DBCC OPENTRAN命令来查看打开的事务。
存储过程
Use Set NOCOUNT ON in stored procedures.
在存储过程里使用Set NOCOUNT ON命令。
译注:如果没有打开这个选项,存储过程里的每一个语句会发送DONE_IN_PROC消息,如果你不告诉调用者某个语句影响的行数,就打开这个选项。
Do not use the sp_prefix for custom stored procedures.
不要让自定义的存储过程以sp_开头。
译注:sp_开头的是系统的存储过程,如果自己开发的存储过程也用这个开头,会增加存储过程的查找过程,它会先去master表找。
执行计划
Evaluate the query execution plan.
评估查询的执行计划。
译注:在查询分析器里写好sql,按ctrl+l就可以看执行计划了,具体怎么看大家可以查下资料,如http://technet.microsoft.com/zh-cn/magazine/2007.11.sqlquery.aspx。
Avoid table and index scans.
避免表和索引扫描。
译注:看到查询计划里的表扫描和索引扫描应该引起你的注意,看看能不能创建适当的索引而让操作改成index seek。不过如果表的数据很少就几百行的话有时候index scan比index seek性能要好,io少。
Evaluate hash joins.
评估哈希join。
译注:如果一个字段上没有索引,在做join里才会使用hash join,而且这个操作比较耗费CPU,如果发现你的数据库进程CPU比较高,可以用profler跟踪下是否有大量的hash join。一般在并行执行查询的时候才会利用hash join,然后再汇集结果,这是hash join的最佳使用场景[不确定我分析的对不对])。
Evaluate bookmarks.
评估bookmarks lookup。
译注:Bookmark就是非聚集索引叶级页上的一个指针,指向了数据页,可能指向聚集索引的根页,也可能指向实际的数据行,如果建立了覆盖索引的话,也许就不用lookup了,只查到非聚集索引的叶级就行了。lookup操作也不一定都是不好的,如果原有的索引选取度已经很高的话,lookup也不会太耗费性能,创建覆盖索引还耗费磁盘空间呢。
Evaluate sorts and filters.
评估Sort和filter。
译注:排序和过滤都是特别耗费CPU和内存的操作,一般创建合适的索引可以减少这些操作。过滤一般还会带来隐式的类型转换,所以要仔细评估。但排序和过滤也并不总是不好,但它可能表示一些隐患。
Compare actual versus estimated rows and executions.
比较实际和估计行及后续操作。
译注:有时候查询计划会利用不正确的统计信息,比如实际的行已经很少了,但统计信息还是旧的,就会引起不是最优化的执行计划。可以使用UPDATE STATISTICS WITH FULLSCAN来强制更新统计信息。
执行计划重编译
Use stored procedures or parameterized queries.
使用存储过程和参数化查询。
译注:最基本的防止执行计划重编译的措施,执行计划的重编译不一定就是坏事,一些初始化的执行计划可能随着实际数据的变化而不再适用,但用参数化查询可以有效的防止不必要的执行计划重编译。
Use sp_executesql for dynamic code.
为动态的代码使用sp_executesql存储过程。
译注:sp_executesql可以为你的动态代码保存执行计划,但如果每次动态代码都不一样的话,执行计划也用不上,也就没缓存的必要了,这个根据需要来吧。
Avoid interleaving data definition language (DDL) and data manipulation language (DML) in stored procedures, including the tempdb database DDL.
避免在存储过程里交错的使用DDL和DML,包括对临时表。
译注:如果要在存储过程里写DDL和DML语句的话,把DDL写在最前面,然后紧接着写DML,最后再对新的对象进行操作。别刚定义了个表,然后往里插了一些数据,最后又写给刚定义的表创建了个索引,这样会导致大量的执行计划重编译。
Avoid cursors over temporary tables.
避免在临时表上面使用游标。
译注:在临时表的数据上定义游标几乎总会引起执行计划重编译。
SQL XML
Avoid OPENXML over large XML documents.
避免在特别大的XML文档上使用OPENXML。
译注:这好像是SQL2000的API,打开特别大的XML会消耗SQLSERVER的缓存。如果确实要导入特别大的XML文档的话,考虑使用 XML Bulkload,具体细节请查资料,如http://blog.500wan.com/u/4/3240/Show.asp?/_articleid/15470.html。
Avoid large numbers of concurrent OPENXML statements over XML documents.
避免在XML文档上进行大量的并发OPENXML操作。
译注:有时候可能想用SQLXML进行批量插入等,但如果该操作非常频繁,会引起内存和CPU升高,应该用其它的办法来取代,比如SQL2008的批量插入,ado.net的bulk copy等。
以上两点都是SQL2000下的SQL XML的注意事项,欢迎大家补充新版本SQLSERVER的XML方面的检查点。
调优
Use SQL Profiler to identify long-running queries.
使用SQL Profiler来标识长时间运行的查询。
译注:现在用DMV和Management studio的报表功能就能看到了。用SQL Profiler的话使用TSQL_Duration模板能找到长时间运行的查询,这些查询会严重影响数据库性能,解决了他们对数据库性能提升有很大的作用。
Take note of small queries called often.
注意到最常调用的小的查询。
译注:以前可能要抓很长时间的profiler trace,然后用fn_trace_gettable自己生成报表来找出这些最常用的查询,现在DMV可以很方便的告诉你,找到这些常用的查询,然后把他们优化到最好。
Use sp_lock and sp_who2 to evaluate locking and blocking.
使用sp_lock和sp_who2来评估阻塞和锁定。
译注:关于阻塞和锁定还有好多计数器,也可以结合着来解决问题。在sp_lock的结果里要特别注意表锁,如果有大量的表锁出现的话可能是导致数据库性能下降的原因。
Evaluate waittype and waittime in master..sysprocesses.
评估master..sysprocess表里的waittype和waittime数据。
译注:可以通过sysprocesses表查看一些锁定和阻塞的信息,以帮助排查,但过程很复杂,提供两个链接给大家http://support.microsoft.com/kb/244455/zh-cn,http://support.microsoft.com/kb/224453/zh-cn
Use DBCC OPENTRAN to locate long-running transactions.
使用DBCC OPENTRAN命令来定位长时间执行的事务。
译注:多次运行该命令,发现每次都有相同的事务,可能就一个长时间的事务,应该确认下这是否正常。
测试
Ensure that your transactions logs do not fill up.
确保你的事务日志不会被填满。
译注:测试环境一般数据量很小,事务量也少,要考虑上生产环境后大的事务吞吐量不会让日志填满,这可能要设置合适的日志增长方式及增长量及磁盘空间。
Budget your database growth.
估算你的数据增长。
译注:根据你的系统的用户量,活跃度,人均信息量等来估算。
Use tools to populate data.
使用工具来生成测试数据。
Use existing production data.
使用现有的生产环境数据。
译注:如果你的系统已经上线了,比如在做第二期,你可以把生产环境的真是数据拿下来当测试数据,这些数据下的测试应该更有真实,更说明问题,他表示了真实的用户模型。
Use common user scenarios, with appropriate balances between reads and writes.
使用常见的用户场景,来模拟适当的读和写的平衡。
译注:一个侧重写的数据库系统和相对读比较多的数据库系统的优化方案肯定是不一样的。
Use testing tools to perform stress and load tests on the system.
在你的系统里使用测试工具来进行压力和负载测试。
监控
Keep statistics up to date.
让统计信息保持最新。
译注:最好打开数据库的统计信息自动更新的选项,如果用profiler监控到Missing Column Statistics事件,可能是有些列丢失了统计信息,这会造成执行计划引擎选择非最优化的执行计划,使用sp_updatestats或者 UPDATE STATISTICS来手工更新统计信息。数据库调优不是一下就作好了,是一个持续的过程,所以我们要经常监控数据库的行为。
Use SQL Profiler to tune long-running queries.
使用SQL Profiler去调节长时间的查询。
译注:这个操作要定期做,因为随着时间的变化,可能会出现一些新的长时间的查询。
Use SQL Profiler to monitor table and index scans.
使用SQL Profiler监控表和索引扫描。
译注:同理,也得定期作,因为统计信息会随时间变化,从而有可能会引起执行计划的错误决定。
Use Performance Monitor to monitor high resource usage.
使用性能监控器来监控高的资源利用情况。
译注:SQL有很多计数器,打开性能计数器可以一个一个的查看都表示什么意思,内存,CPU,磁盘和网络一般都列为常规的监控列表中。
Set up an operations and development feedback loop.
经常安排运维人员和开发人员的相互交流。
译注:这句直译译不出来,大概是这个意思,开发人员一般不具备生产环境的访问权限,运维人员应该经常把生产环境的数据库情况反馈给开发人员,开发人员也应该告诉运维人员应该注意观察些什么。
部署上的考虑
Use default server configuration settings for most applications.
为大多数的应用使用默认的服务配置。
译注:不要轻易的修改SQLSERVER的配置项,这样做很可能会降低数据库的性能和可伸缩性,下面这个链接列举了一些常见的SQL配置,是SQL2000的http://support.microsoft.com/default.aspx?scid=kb;en-us;319942。
Locate logs and the tempdb database on separate devices from the data.
把tempdb数据库和日志放在不同的存储设备上。
译注:修改数据会记录日志,如果你用到临时表的话会有数据写在tempdb里,把他们两个和主数据库放在不同的磁盘上能大量的提高性能。
Provide separate devices for heavily accessed tables and indexes.
为大量访问的表和索引提供单独的设备。
译注:如果你的某给表或者索引预计会有I/O瓶颈,把他们放到不同的文件组,甚至放在不同的磁盘里以减少瓶颈的发生。
Use the correct RAID configuration.
使用正确的磁盘阵列配置。
译注:对数据库服务器来说,要使用硬件的raid,别用windows的跨区卷带区卷等作的软riad,那会增加CPU消耗。常用的RAID是raid 5和raid 0+1,你选择RAID的级别,要综合考虑成本、性能和可用性的的要求。RAID5比RAID 0+1成本低,读性能比写性能好,raid0+1成本更高一些,但提供了更好的写性能,比如tempdb更应该用raid 0+1.关于raid的选择,大家看http://storage.it168.com/h/2007-06-12/200706121108656.shtml。当然有钱的话还可以用san,如dell的cx300,cx500,cx700等。
Use multiple disk controllers.
使用多个磁盘控制器。
译注:让一个磁盘控制器管理多个磁盘可能会引起瓶颈。
Pre-grow databases and logs to avoid automatic growth and fragmentation performance impact.
估算你的数据库和日志的增长趋势,以避免因自动增长和随便对性能的影响。
译注:如果你启用了文件自动增长,要确定一个合理的增长选项,你可以选择按百分比增长,还是每次增长一个固定的大小,尽量每次长的大一些,这样可以尽量避免频繁变动数据库大小。甚至你可以用计数器监控磁盘的使用,而在业务低谷的时候去扩盘或者收缩文件,而不是启用自动增长和自动收缩。关于这些配置可参考:http://support.microsoft.com/kb/315512/zh-cn。
Maximize available memory.
最大化可用的内存。
译注:启用AWE,打开/3G开关。监控SQLServer:Buffer Manager:Buffer cache hit ratio 计数器,应该在90左右,这个值太低说明缓存命中率太低,应该添加更大的内存。Memory:Available Bytes计数器如果显示太少,表示可用内存太少了,需要加大内存;SQLSERVER有一个Buffer pool来管理内存,如果SQLServer:Buffer Manager: Free pages计数器持续小于4达两秒以上,数据库就会变的很慢,你就得加大数据库或者用profeler查看是不是有大量的hash操作或者排序操作。另外如果你的机器上运行多个数据库,你不要让其中一台数据库把物理内存全占了。
Manage index fragmentation.
管理索引碎片。
译注:数据库运行时间长了,肯定会造成索引碎片,使用DBCC SHOWCONTIG命令可以查看碎片情况,你可以删除索引,重建索引,使用DBCC DBREINDEX 或DBCC INDEXDEFRAG 命令来去除索引碎片,其中前两种方法会锁定资源,以导致用户无法进行有效的操作,DBCC INDEXDEFRAG可以在线的重建索引而不锁定资源。SQL2005有联机重建索引的功能。
Keep database administrator tasks in mind.
保持数据库管理员的应做的思考和任务。
译注:这句不知道咋翻译,考虑备份对性能的影响,统计信息更新,DBCC检查,索引重建等。