关灯
《文稿,还能这样写》作者雄文《笔杆子碎语》作者王一端《机关文稿写作入门》作者杨新宇《机关文字工作五十讲》作者何新国
最新《公文写作培训课程》直播间《公文写作百法例讲》作者房立洲老秘网站长、《老秘笔记》作者老猫《公文高手的自我修养》作者胡森林
开启左侧

浅谈优化SQLServer数据库服务器内存设置的策略

[复制链接]
文秘114 发表于 2009-10-8 16:55:17 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题
文稿修改演播室众筹计划,点击了解详情
 
浅谈优化SQLSe。笔者经过仔细摸索,发现系统对硬、软件的需求较高,为充分发挥设计效能,达到最佳运作效果,需要对计算机硬、软件系统进行较为完备的性能测试和最佳设置,特别是内存设置的好坏对系统的运行速度具有决定性的作用。下面,笔者就怎么优化SQLServer数据库服务器的内存设置提出一些认识和看法。

一、有关内存的基本概念

  1?物理内存和虚拟内存
  视窗系统NT使用两类内存:物理内存和虚拟内存。
  物理内存:作为RAM芯片安装在计算机内部的存储器。
  虚拟内存:用于模拟RAM芯片功能的磁盘(硬盘)空间,其实质是通过将内存中当前没有使用的部分内容临时存储到磁盘上,使系统能使用到比机器物理内存更多的内存。
  2?分页和分页文件
  视窗系统NT系统通过使用磁盘空间使得对内存的需求得到部分缓解,从而使用到比物理内存更多内存的技术就称为“交换”或分页,也就是通常所说的虚拟内存技术。通常视窗系统 NT 4.0系统安装时将在引导驱动器上设置一个大小为16MB的交换(分页)文件(pagefile.sys)。

二、优化视窗系统 NT 4.0系统内存设置

  在大多数情况下,为了充分发挥视窗系统 NT 4.0系统效能,内存的作用比起处理器的处理能力更具有影响力,特别是在客户/服务器模式环境下更是如此,因为通常在这种环境下并不十分强调处理器的能力,相反却十分注重是否采用足够的内存来满足各个客户的应用需要。此外,为了获得容错功能和保护应用程式,确保应用程式高速运行、充分发挥设计功能都需要有足够多的内存,特别是工业绘图设计和各种工程应用程式更需要占用大量的内存来进行复杂的计算。
  物理内存(RAM)方便快速的好处显而易见,但由于其价格昂贵,也就不可能做到多多益善了,因此通过合理优化内存设置、扩充虚拟内存提高计算机运算速度也就成了一项非常重要的应用技术手段。
  1?确保视窗系统 NT系统基本内存需求
  视窗系统 NT 4.0系统至小应设置12MB内存,16MB内存基本够用,正常情况下确保NT系统有32MB内存就能了,因为并不是所有的16MB基本内存在所有时候都被同时使用。如果添加一些服务和应用程式,则对内存的需求就会急剧增大。如:
  (1)添加网络服务需要4MB内存空间;
  (2)容错功能和系统保护功能需要8MB内存(如磁盘映像和分条功能);
  (3)进行图像图象处理需要增加16MB内存空间;
  (4)安装VC、VB研发系统需要增加16MB内存空间;
  另外,如在视窗系统 NT上构建大型数据库如SYBASE、Microsoft SQL Server等,对内存的需求就更多了。
  2?优化内存性能
  为了使视窗系统NT不至于过分占用较多的内存或浪费处理器的时间用于换页,能采用以下方法优化内存性能。
  (1)减少显示颜色的数量;
  (2)降低显示分辨率;
  (3)尽可能不使用或使用位宽度较小的墙纸;
  (4)关闭不必的服务程式或驱动程式,尽量不要在服务器上使用其他应用程式。
  停用服务或驱动程式的操作步骤如下:
  ①确定需要停用的服务或驱动程式的名称;
  ②从“控制面板”中双击“服务”或“设备”图标;
  ③在列表中选择想要停用的服务或设备驱动程式的名称,单击“停止”按钮,这时出现确认操作对话框;
  ④选择“是”确认操作,然后关闭对话框完成设置。
  3?优化虚拟内存
  在对视窗系统 NT虚拟内存进行设置时需要合理确定各个驱动器分页文件的“起始大小”和“最大值”两个参数,他们用于指定分页文件的起始空间和最大空间。下面对这两个参数作一些解释:
  起始大小:指初始创建该分页文件时的文件大小,单位为MB,根据缺省设置,这个值被设置为系统中的物理内存的大小。
  最大值:指出该分页文件的最大尺寸,单位为MB。
  (1)分页文件的设置原则:
  ①分页文件起始大小应保留缺省设置,一般情况下请不要改动;
  ②分页文件最佳的最大尺寸为系统物理内存尺寸的2.5倍至4倍。需要说明的是:如果系统工作时不必大量内存,请选择靠近下限的值,即用系统物理内存的2.5倍作为这个尺寸的起始值;如果系统工作时需要大量内存,请选择靠近上限的值。
  (2)视窗系统 NT虚拟内存设置步骤:
  ①从“控制面板”中双击“系统”图标;
  ②在“系统特性”对话框中单击“性能”标签;
  ③在虚拟内存对话框中单击“更改”按钮,这时出现“虚拟内存”对话框,上端的驱动器框逐一列出了 视窗系统 NT所有页面文件的大小;
  ④在驱动器列表中,选择需要设置分页文件的驱动器盘符,在“驱动器页面文件大小”对话框中列出了 “起始大小”和“最大值”两个参数栏,填入按照上面的原则确定的数值;
  ⑤单击“设置”确认以上操作,然后依次单击“确定”按钮退出各个对话框,完成设置。
  (3)Win95/98虚拟内存设置。
  Win95/98虚拟内存设置方法、步骤和原则和视窗系统 NT 4.0的设置大致相同,请参照上面视窗系统 NT的设置。
  4?注意事项
  (1)合理确定分页文件的最大值,根据系统需求随时进行调整,使用过多虚拟内存将导致整个系统处理性能的下降。设置虚拟内存最大值的目的是使用户不必在视窗系统NT的交换文件上消耗过多的磁盘空间,通常情况下如果超过了系统需要的最佳值后,生成交换文件的磁盘空间就被浪费了。
  (2)尽可能设立专用硬盘设置内存交换区,或将交换空间放到主硬盘的另一个分区,同时应将主硬盘的交换文件大小降至16MB,这样主硬盘(分区)仅用来放置操作系统和应用程式,就能减少交换次数,防止频繁交换耗费大量 CPU时间。
  (3)虚拟内存技术的确改善了视窗系统 NT系统的性能,但也受到机器硬盘空间大小、硬盘速度、处理器 (CPU)速度的影响,从最佳角度出发,要提高计算机的性能就必须减少交换操作的次数,不过没有一个视窗系统NT计算机不发生交换,这就需求计算机要有足够的物理内存,以保持最少的交换操作。

三、优化Microsoft SQL Server数据库内存设置

  内存是影响Microsoft SQL Server系统性能的一个重要因素,SQL Server数据库安装时将为具有32MB物理内存的机器缺省设置16MB可用内存,16MB物理内存的机器缺省设置4MB可用内存。应在Microsoft SQL Server数据库安装后进行内存选项(Memory)设置,最大设置值为2GB。
  为了确定SQL Server系统最适宜的内存需求,能从总的物理内存中减去视窗系统 NT4.0需要的内存及其他一些内存需求后综合确定,最佳的情况是给SQL Server分配尽可能多的内存,而不产生页面调度。
  1?根据物理内存合理规划SQL Server可用内存
  在大多数的生产环境中,服务器配备的物理内存是64MB~128MB,偶尔也有256MB的,只要设置恰当是完万能满足SQL Server的内存需求的。下表是笔者关于SQL Server内存分配的建议规划,供参考。


物理内存 分配给SQL Server 设置值(单位:2KB)
8MB 4MB 2048
16MB 8MB 4096
32MB 16~18MB 8192~9216
48MB 28~34MB 14336~17408
64MB 40~46MB 20480~23552
128MB 100~108MB 51200~55296
256MB 216~226MB 110592~115712
512MB 464~472MB 237568~241664

  以下是SQL Server内存选项(Memory)设置方法
  (1)从Microsoft SQL Server程式集中启动SQL Enterprise Manager;
  (2)从Server Manager窗口中选择“Server”菜单选项;
  (3)在“Server”菜单中选择“Configurations”选项;
  (4)在“Server Configuration”对话框中选择”Configuration”标签,Configuration窗口显示设置选项列表;
  (5)选中“Memory”项目,在“Current”栏填入新值;
  (6)停止并重新启动SQLServer服务,使设置生效。
  2?合理扩充虚拟内存、增大SQL Server可用内存
  当SQL Server系统确实需要扩大可用内存时,应在磁盘空间充足的情况下扩充供虚拟内存,并相应增大 SQL Server可用内存。具体做法是,系统管理员首先扩充服务器的虚拟内存,然后再参考上表增大SQL Server可用内存,关键是要根据系统的负载情况综合决定是否扩充内存、优化设置。
  3?使用tempinRAM
  SQL Server使用tempdb临时数据库作为一些查询连接操作时排序或创建临时表的工作空间。将tempdb创建在RAM中能使系统操作性能有较大提高,而且因为tempdb在每次重启动服务器时都重建,这样即使有非正常的关闭也是较为安全的,例如停电故障。要将tempdb创建在RAM中,能使用sp_configure进行设置,具体用法请参阅有关资料。
  由于tempdbinRAM使用的内存是由系统从内存体独立分配的,和SQL Server的内存选项设置的可用内存池是分开的,使用tempdbin RAM将减少整个系统的可用内存,应根据SQL Server和服务器运行情况进行设置,否则就可能适得其反,影响系统性能。另外,适当增加tempdb数据库空间,即使不使用tempdbin RAM,也能提高数据库的运行速度。
  4?注意事项
  (1)建议在生产环境中SQL Server不要设置小于32MB内存,而且数据库服务器上尽量不要运行其他应用程式;
  (2)扩充供虚拟内存、增大SQL Server可用内存,应考虑物理内存使用状况和磁盘空间许可情况;
  (3)在可能的情况下,要为系统留有部分额外的内存,这样在服务器上打开一个服务或添加一个进程且不改动SQL Server内存设置时,不致于使NT服务器的运行速度受到影响(变得非常慢),一般认为最小为2MB最大为20MB。
四、巧用内存设置,解决统计服务器问题

  一单位的统计服务器投入使用后,运行速度较慢,经排查原因,发现SQLServer中的内存选项(Memory)仅为安装缺省值??16MB(而服务器有128MB的物理内存),在将内存值调整为100MB时却误将其改成了 1000MB,使得SQL Server服务不能启动,统计数据库打不开,也就不能再次进入SQL Enterprise Manager修改内存设置了。由于近期未备份业务数据,不到万不得已不能重装SQLServer数据库,就试图用命令行参数命令来重新启动SQL Server服务,但均不能奏效,陷入了困境。我们经过仔细分析提出:既然SQL Server可用内存设置值远远大于物理内存,造成SQLServer服务不能启动,何不扩充虚拟内存呢?经设法将机器虚拟内存扩充至1000MB并重新启动,SQL Server数据库成功启动,问题迎刃而解。

五、结束语

  目前,大多数单位投入使用的Microsoft SQL Server数据库服务器的物理内存一般都在64MB以上,如农业银行省、市分行的统计服务器配备128MB物理内存,只要按照上面提出的方法合理规划、优化NT和SQL Server的内存设置,使设置尽可能达到最优,应用系统就一定能够充分发挥设计功能、满足业务需求。□ rver数据库服务器内存设置的策略
 

精彩评论6

正序浏览
大明老秘 发表于 2009-10-8 18:21:15 | 显示全部楼层
 
公文写作百法例讲
客户端:  
  sql:='Select   top   n   from   tablename   where   id>'+curmaxid;  
  Datas:=ClientDm.ATest.MSearch(Sql);  
          if   Not   VarisNULL(dATAS)   THEN  
          BEGIN  
              CdsTypes.Close;  
              CdsTypes.Data:=NULL;  
              CdsTypes.Data:=DATAS;  
              DATAS:=Null;  
          END;  
   
  用语句来控制的查询,,分页等。这样服务器始终保持最小的内存使用状态!!!说的有点模糊,,见晾  
 
大明老秘 发表于 2009-10-8 18:29:23 | 显示全部楼层
 
老秘网虚拟稿费

SQLServer2000里自动重建索引

6 b( A' ~% b5 v" C' g7 O2 x

SQLServer2000里自动重建索引

' @) I* J2 b7 b4 f V3 g6 R6 l* F

--王成辉翻译整理,转贴请注明出自微软BI开拓者www.windbi.com

$ ]& ^( _- O. P- w& u0 X

--原帖地址

- `8 ^! _ h6 ~4 w: k$ X

在所有的OLTP环境里,实质上所有的索引都将随着时间产生碎片。几乎所有的UPDATE、INSERT、DELETE活动都将引起索引比最初创建时变得更无组织。页拆分更多,大量的页上只有很少的数据,因此满足每个SELECT需要更多的I/O。数据和索引的碎片越多,应用程序就会更慢,数据花费的空间就更多。对此你能做什么呢?你可以定期的重建索引。 

4 i8 ?" C" ~. a/ d, L

那么什么可以立即使用呢?

% K, F* F# R, S) C

基本上你可以使用数据库维护向导来执行索引重建,创建维护计划来完成。如果你原意接受它固有的缺陷,这也可以使用。首先,用维护向导来配置和完成索引重建是不慎重的。它将重建每一个索引,不管它是否需要重建。如果你有一个有很多大表和大量索引的大数据库,这会出问题,因为不加区别的重建整个数据库的索引会花费很长的时间,会使你的维护窗口不可用。问题在于,要么全部重建,要么全部不重建,你根本不能以任何方式分批处理数据库的表。

' [! C! y. f4 L+ {, Q- Z

 

' D# M7 t& c9 c8 g

 

P& Y& z3 {) a

那么有什么别的能做吗?你可以写一个脚本来重建选择的表的索引。这样你能对数据库分批处理以减少在重建索引时你维护窗口执行的时间。你需要将这个时间减小到最少,因为重建索引会对表执行排它锁,在重建索引期间禁止用户访问。所以你可以每周的每个工作日的晚上重建五分之一表的索引,所有的索引至少一周做一次。然而,这也是不慎重的――你将重建所有表的索引而不论数据和索引是否是有碎片。

, m! c) F( P; u+ C- }

这里推荐选择性的重建索引。你需要检查表的索引和数据的碎片,保留数据,据此操作,重建索引要用确定的且区别对待的方式。仅仅通过这样系统的方法,你可以仅重建那些实际需要重建的表的数据和索引。而且也只有这种方式能最小化索引重建的时间。在整个索引重建期间,如果你不想影响你的用户的话,减少索引重建的时间是至关重要的。

1 }. H2 C; {6 a' }3 V+ ]6 B

那么我们怎样可以解决呢?

7 k, E( Z' g2 J% \# f* |

可以使用命令

- O. S$ i. m' d( Q/ A3 X

DBCC SHOWCONTIG()

1 ^5 _9 h% u2 U) L& @- W: c

SQLServer2000比以前版本有一个大的改进就是这个简单而又至关重要的命令。DBCC SHOWCONTIG是SQLServer提供来检查索引碎片情况的工具。在以前的版本里(7.0和更早的版本),这个命令只输出文本,如果手工处理这个命令很好,然而,要实现自动化目的,它会带来严重的问题。那意味着你要循环执行每一个表并将结果输出到文本文件,然后为了读和解释原文的输出结果以便获得你寻找的信息,需要进行烦人的结构化处理。

; Z3 C" h' n7 v# |& o# t

SQLServer2000对DBCC SHOWCONTIG()命令引进了一个关键子句,名为WITH TABLERESULTS。这意味着你能运行这个命令然后将捕获的数据直接输出到表里,而不是还需要使用XP_CMDSHELL来操作的文本文件里。

% ~# K p0 q& A( W& \: q2 e

在SQLServer2000里,这意味着你能结构化的循环处理表,通过在它们上面运行DBCC SHOWCONTIG命令以将捕获碎片信息插入表中。然后你能循环使用这个结果,根据碎片的情况,选择性的进行碎片整理。可以用下面的存储过程实现:

) c6 G; o, O/ l) h# h# ]* N

CREATE PROCEDURE sp_defragment_indexes @maxfrag DECIMAL

0 E. S- {' ]/ F# E

AS --王成辉翻译整理,转贴请注明出处

7 c1 E4 o4 b, h) k

--声明变量

% X5 L8 O+ c4 c9 a. \7 g. H

SET NOCOUNT ON

2 l/ T3 \" o5 o9 h6 }" U- J7 G& y

DECLARE @tablename VARCHAR (128)

0 y4 j' F3 r Z# r/ e, V- Y" i

DECLARE @execstr VARCHAR (255)

% b9 g: s; { o ?+ f

DECLARE @objectid INT

; T0 e ]) Y9 @; _8 s

DECLARE @objectowner VARCHAR(255)

% \$ y; X2 d- G

DECLARE @indexid INT

) a; W: N ?4 {* g% B4 p& q

DECLARE @frag DECIMAL

5 `) U# j1 k; c4 _- }

DECLARE @indexname CHAR(255)

! s0 E' T5 k$ B+ F9 }: J

DECLARE @dbname sysname

9 D: ]5 @& @" O B9 l

DECLARE @tableid INT

! p, n. k% A) H: X9 B

DECLARE @tableidchar VARCHAR(255)

8 W6 E8 o! e8 B& k# \1 e+ M

--检查是否在用户数据库里运行

6 y' D; V3 K; \( B: D

SELECT @dbname = db_name()

; Z: l' X) H& T' n( `

IF @dbname IN ('master', 'msdb', 'model', 'tempdb')

# H j9 X) @& Q: Q

BEGIN

L2 Z, n! d/ ]0 z9 `7 r

PRINT 'This procedure should not be run in system databases.'

: {: D# |+ r+ f' X& f- Y/ j

RETURN

- n( l7 I+ u2 |7 ?

END

}' t/ Y' i. |1 U4 H" j+ m5 u, x1 N4 N

--第1阶段:检测碎片

4 }5 v$ j. i0 v" ^+ P

--声明游标

! Q: ~: X _% D; _9 r" L+ K

DECLARE tables CURSOR FOR

+ Z) m c9 H6 I7 K" N$ {$ M* y3 h2 t

SELECT convert(varchar,so.id)

2 Q% t# C7 g) o, C

FROM sysobjects so

1 X# M0 w8 G, V- ~: p4 N. M

JOIN sysindexes si

5 E3 a/ w+ `% C) ]4 i

ON so.id = si.id

& \5 H* l! t% f* L8 q" T# @2 K2 d

WHERE so.type ='U'

$ x0 @8 x+ R; I/ `; m( j% ?

AND si.indid < 2

/ {% v, ~( h2 B: e+ X4 _

AND si.rows > 0

* H6 T. ~) c: U& p$ S" f4 u3 l+ H" O

-- 创建一个临时表来存储碎片信息

* _% D9 k) O5 o E* W; e3 ]: I

CREATE TABLE #fraglist (

# M3 u% o: |0 E. v; y

ObjectName CHAR (255),

5 X$ q( G1 h, p- j

ObjectId INT,

o) g i2 j$ \/ m

IndexName CHAR (255),

9 v3 K0 P! b) ?! u2 ?$ o

IndexId INT,

5 D2 K# U1 _, L- `: `4 n3 a; T0 X

Lvl INT,

/ d# y, Z, S; ^% a2 Y8 v* `1 G9 `

CountPages INT,

5 V0 W( A+ _/ I& o& A, O2 c

CountRows INT,

x4 O6 N% m2 v8 `" G

MinRecSize INT,

1 S% K2 @. y n3 _; I+ ?

MaxRecSize INT,

! e/ [3 E% {4 n( d' v

AvgRecSize INT,

! H0 x% I. c+ V- g- U

ForRecCount INT,

2 {6 g+ E. D+ S4 V, @# B

Extents INT,

$ z: s& A- T9 `

ExtentSwitches INT,

' E" x4 W' K) X4 ?5 O3 _7 l" t

AvgFreeBytes INT,

& ~) v; D/ N, L

AvgPageDensity INT,

' \$ f B' P: i" s+ s. E% I

ScanDensity DECIMAL,

! `9 x C5 E/ s6 O( S7 | ]

BestCount INT,

, W0 r3 R7 q b( x4 V) x, o

ActualCount INT,

, _) p3 u0 j7 E5 N! W

LogicalFrag DECIMAL,

3 x: e! _; `! k% d1 @* {

ExtentFrag DECIMAL)

: Z6 l* L/ w$ y3 C/ ]2 y( A

--打开游标

( |; l7 B1 a2 c% |: |, F, L! T

OPEN tables

3 ]8 r; G, p @0 w- a

-- 对数据库的所有表循环执行dbcc showcontig命令

3 u8 ~3 M% Z; C4 }, ?, o7 i

FETCH NEXT

' L- J0 h' R/ F" v. l2 D) d

FROM tables

" ~, z a) Z' \% u& i- o5 x7 R

INTO @tableidchar

5 x2 ]9 L `! V$ H: E" c

WHILE @@FETCH_STATUS = 0

( Z- P. s4 t, ^4 _

BEGIN

/ e h& G/ e w# r6 u* T

--对表的所有索引进行统计

6 Y8 A/ N2 C- e2 ^! U0 q

INSERT INTO #fraglist

6 O. B5 x/ j K' x7 I7 M

EXEC ('DBCC SHOWCONTIG (' + @tableidchar + ') WITH FAST, TABLERESULTS, ALL_INDEXES, NO_INFOMSGS')

' ]$ L5 i( F R

FETCH NEXT

: Z$ i2 Z; {* y3 r4 ~

FROM tables

( l2 R& J' ^1 y0 N

INTO @tableidchar

5 Z& b" H4 j4 r9 ?9 p+ B

END

) e4 {( V! v1 {% o

-- 关闭释放游标

2 _- [. P2 T5 r) q& J2 ]1 t$ r# H B

CLOSE tables

n2 Q& r8 b$ D+ z( V

DEALLOCATE tables

/ S3 {( n% g6 p9 n! z, `3 m3 P$ I

-- 为了检查,报告统计结果

6 [4 ]1 v/ M5 s) |* x! U0 B

SELECT * FROM #fraglist

2 ?$ m! H! ]6 o" {& R k" I8 T: p

--第2阶段: (整理碎片) 为每一个要整理碎片的索引声明游标

1 ?& j% [) S. Q2 O2 G

DECLARE indexes CURSOR FOR

' W; c$ B9 W+ w* m- _; T

SELECT ObjectName, ObjectOwner = user_name(so.uid), ObjectId, IndexName, ScanDensity

( S9 e) ?5 R6 w# G1 E" M9 {

FROM #fraglist f

5 u0 P4 T$ z9 B: c, v

JOIN sysobjects so ON f.ObjectId=so.id

. M2 w6 @ R) J2 k4 b& g

WHERE ScanDensity <= @maxfrag

& b5 j% h3 q- a

AND INDEXPROPERTY (ObjectId, IndexName, 'IndexDepth') > 0

% X/ P6 A$ C# L, [' [, f* b

-- 输出开始时间

8 p8 [0 \: c. [$ }$ [0 G

SELECT 'Started defragmenting indexes at ' + CONVERT(VARCHAR,GETDATE())

; |3 l9 h7 g/ x

--打开游标

$ |) B W0 U6 g1 q) H9 g [

OPEN indexes

i4 j" D% A: V- Q }4 V

--循环所有的索引

* {: C ~7 x9 C. Y# ~

FETCH NEXT

9 P+ o- V: B9 T# ? l

FROM indexes

- V0 `" c. A+ J. l* ]$ \. k

INTO @tablename, @objectowner, @objectid, @indexname, @frag

$ R$ p2 X+ x; Q# U6 d: e$ V

WHILE @@FETCH_STATUS = 0

$ @+ ?# }' s6 N8 p; V" C/ }( t" p

BEGIN

9 S4 n/ {5 B' Y9 X, ?4 {

SET QUOTED_IDENTIFIER ON

: d( j5 \% k/ {. k4 K

SELECT @execstr = 'DBCC DBREINDEX (' + '''' +RTRIM(@objectowner) + '.' + RTRIM(@tablename) + '''' +

7 v: _5 v5 R0 u; |

', ' + RTRIM(@indexname) + ') WITH NO_INFOMSGS'

! [- E) }. Z) {( Z; u3 b4 P& C$ A* F3 Y

SELECT 'Now executing: '

3 h! |$ l( B# J+ p

SELECT(@execstr)

8 @' P# X* O$ Z0 o8 D5 H$ k( {

EXEC (@execstr)

' Y. F: g5 ~ J; E. b

SET QUOTED_IDENTIFIER OFF

( z# p$ D' k* J( R6 d/ V

FETCH NEXT

/ L/ W* e: _- q9 Y2 \

FROM indexes

* p6 w$ t8 I7 v- |

INTO @tablename, @objectowner, @objectid, @indexname, @frag

! g6 Y, f# w: x5 a

END

. V0 _+ M5 c7 X, `* D* m

-- 关闭释放游标

2 T0 u7 p* p) g& }/ m9 {0 R5 I

CLOSE indexes

! K1 S1 J! p4 A. I$ \

DEALLOCATE indexes

" G8 K' C h4 M

-- 报告结束时间

' R! |2 W8 R r- \7 [5 I

SELECT 'Finished defragmenting indexes at ' + CONVERT(VARCHAR,GETDATE())

8 G. D! I* X. q3 q( t0 I

-- 删除临时表

# X: r) H4 V; z, p

DROP TABLE #fraglist

" f$ W) v* }& }' e+ j; A

GO

6 }0 m6 T) t8 i$ @; Q" `, Q

使用

# u+ q' H( p) Z9 {$ V% `

这个存储过程应该创建在master数据库里,以便你能在服务器上的任何用户数据库里使用。

6 J6 c/ E" A2 n5 h! y

在用户数据库里通过传递一个参数(MAXFRAG)来运行。该参数是一个百分比值。意思是任何索引的碎片扫描密度小于这个值。例如,如果你想要整理那些扫描密度小于95%的索引的碎片:

. m# v# O% f+ H! m

USE pubs

' g; c( Y6 g* v& n1 G

GO

9 r' R+ m! y$ W& w: v# Y

EXEC sp_deframent_indexes 95.00

# P& X8 ~$ ?3 W: p7 ^

局限

) S# f( W% Y$ B& z5 y O9 j: G: n

这个过程依赖于的标准是扫描密度,但扫描密度对于那些跨越多个文件的索引来说不是一个有效的标准。如果你的索引确实跨越多个文件,你需要用另一个标准(如Logical Frag)来更改这个存储过程。然而,这类更改超过本文的范围;如果你的索引跨越多个文件,你需要做更多的工作。 

, G4 @' O! }* s! K7 p% q; G2 Z

怎样做,做什么?

) ?" q- |$ _3 U

这个存储过程有两个独特的部分。

1 t% ?5 c# s! W5 J2 `- E5 {

第1阶段

2 t- y( I2 N9 e; D2 R7 j+ V

在这部分里,存储过程通过在数据库里的每个表上运行下面的命令来检查索引碎片:

- i$ N, R5 U# @+ [9 u8 i

DBCC SHOWCONTIG (‘tablename') WITH FAST, TABLERESULTS, ALL_INDEXES, NO_INFOMSGS

1 I9 S# u+ t: S9 j" a2 q) d; U2 ~9 h8 c

命令的结果存储在预先创建的临时表#fraglist里。这里就会用到DBCC SHOWCONTIG 语句的WITH TABLERESULTS的好处,仅这一点,真正的节省了太多的以前版本得到同样结果所花费的麻烦和精力。

4 [0 y, V9 F0 s

你应该注意该存储过程工作的数据库的表的拥有者是不是dbo,通常是。我发现我最初的版本不起作用,当时一个软件经销商给我们提供的新系统的数据库里就出现了拥有者不是dbo的表。当我在这个新系统上第一次运行我的碎片整理过程时,这个程序的缺点就暴露无遗了,最后彻底失败。这个问题实际上出现在碎片整理阶段(阶段2),因为表在这里要引用表名,而在阶段1,DBCC SHOWCONTIG命令引用的时表的ID即object_id。

" I# W% A3 j* n9 Y7 O

第2阶段

. h6 [: n7 H h* V% w6 N0 R; C

这儿使用了另一个游标来循环处理表#fraglist里的记录,这些记录是那些扫描密度低于传给存储过程参数的那个阈值的表:

4 x3 Z! w" [/ O% p

DBCC DBREINDEX()

4 T+ O: U6 `! j5 N- b

执行的结果以输出文件的形式显示在表#fraglist的内容之后,以便你能查看表和索引的碎片,正如屏幕上所显示的那样,也可以通过查看DBCC DBREINDEX()执行的结果列表来查看采取的动作。利用这些你也能推导出每个索引重建的时间。 

+ b6 S& q1 g" ]

输出结果是什么意思?

! @8 k q$ l: m) n. z' s2 z9 b

输出示例:

7 n( r$ M8 x ~* Z- Y

 SQLServer2000里自动重建索引 - yanam0518=

$ M8 a% ~0 e2 d" }# I" S& h# P3 r

上面是在Excel里打开的存储过程输出文本文件的一个截屏。为了简洁一些列已经删掉了。你需要用文本文件向导来打开它,选择固定列宽,打开导入从第三行起。

2 X+ {. q! c5 u* o/ h3 U7 d

这里,你能够检查你选择检查的数据库里的表的扫描密度。

) H- w8 t7 a$ @, u& n

在接下来的输出文件里(DBCC SHOWCONTIG输出结果的后面),你会发现正被重建索引的每个表或索引的细节,这部分的开始和结束部分都有重建索引的开始和结束时间。如下面例子显示的那样:

, }5 k$ \5 q# o. j0 t7 I7 Q! F

SQLServer2000里自动重建索引 - yanam0518=

) r z( w* ~- [* B$ Q( J% w

为什么不使用DBCC INDEXDEFRAG()去减少阻塞?

) |) G7 f' n+ F5 t. Z$ ]7 B; m, @

答案是如果你想要或者需要的话就使用它。如果你需要7×24小时的在线操作,那么DBCC DBREINDEX()的排他表锁不适合你的业务,你可以使用它来代替DBCC DBREINDEX()。然而,你需要适当改变一下语法,因为它们是不相同的(谢谢,微软!)。如果你不知道它们的区别,这里有一个简单的摘要:当运行DBCC DBREINDEX()的时候,必须对表有排他锁,因为它是一个完全的,彻头彻尾的索引重建操作。而DBCC INDEXDEFRAG()就不那么完全了,在线的操作试图改善你索引的环境而不至于引起阻塞和中断OLTP(希望如此)。我必须承认我从来不用DBCC INDEXDEFRAG(),因为很幸运的是我的系统不需要严格的7×24在线且要求不阻塞,所以我不敢担保是否有效率。我已经理解它不是和DBCC DBREINDEX一样有效率。然而它的确比什么都没有强,所以如果你的数据库运行一个全球的WEB站点并且从来不能停止,这在今天这也很普遍,那么你需要使用它来代替以改变这个存储过程。 

$ O' Y8 \! j0 z/ y) U

添加到调度任务里

) _# r/ M) Y+ \3 ~4 q

对于有相当经验的DBA来说这是一个相关的微不足道的任务,所以我在这里不会提供它的代码。作为一个独立的任务或在你存在的维护作业里的一个步骤都行。你要确保作业的步骤或作业里的输出结果是一个文本文件以便你能保存和查看所有重要的输出文件。 

! k* d" w) [0 a+ A2 j9 Y8 i

结论

5 D2 _ y4 ~9 ^ f! t

希望这篇文章和代码能帮助你完成一个对数据库服务器维护来说更好的更精确的方法。现在的维护窗口开销很大,所以在影响用户和执行时间上保持最小的同时也提供了有效率和良好的数据库服务器维护。用调度作业实现这个过程,小心的监控它的输出结果。

 
大明老秘 发表于 2009-10-8 18:31:23 | 显示全部楼层
 
专业写文章
http://topic.csdn.net/t/20050115/10/3727581.html
 
大明老秘 发表于 2009-10-8 18:32:50 | 显示全部楼层
 
--执行这个语句  
  exec   sp_configure   'min   memory   per   query',1024
 
大明老秘 发表于 2009-10-8 18:33:18 | 显示全部楼层
 
1。   你的内存设置的太小了!企业管理器--右键SQL实例--内存--选择"动态地配置SQL   Server内存--将最小值设置为0--最大值设置大一点  
  2。   要不就是你的内存容量不够了!需要加内存容量
 
大明老秘 发表于 2009-10-8 18:36:13 | 显示全部楼层
 
MSSQLSERVER_8651
5 D5 N' Y$ V% o, s& r0 d: v* i
: T* d; c8 w5 k1 l% b9 H* m6 E& f
9 i0 X6 {7 k4 G' c0 A u

1 m0 k& f. O8 s0 {1 Q; Z
( _. d( r# Z, g9 `" D 4 |1 A+ |! z* c- }
' Q) D/ c: T r1 \

) [3 x D! z" b" T% U* u) t3 Y* R; S$ X+ {2 P0 Y$ l. f/ ?3 E1 S2 h" b0 z* w8 d f8 D3 K- I' n: z6 ]: f5 V5 w3 N* L; a: ^6 Y0 t4 L# [ v+ k) Y9 ], m) u% z8 H- l8 w' r( f$ {8 [6 `2 ]( s$ \3 p X P3 f/ E* D' A/ ~( m' M4 a% y7 D( H- [5 [9 Q7 I8 \6 X; Q: A3 h/ r/ r0 A) V0 R6 ?5 l, ~8 A( f n; q" }9 x* D9 S( P) M- \; C1 S) `8 E& P) |+ p: @& Z% {" z/ x' v& g% q2 ?* [9 _2 Z- W! m1 H: e2 P7 e, y4 ^+ D2 `; }0 o7 y8 ~4 Q0 U+ @3 D& k j& k+ G' O& x" ? ~0 ?3 H# T7 g. s+ D6 B# i- O( D; ?! E" I2 }7 `9 h: a5 F& Y# r# F4 l- l1 h3 t7 A" K6 t3 g) I! W7 ]6 r% f- M9 p3 Y. o( B. l9 s% i! @& a! i* X" N$ e$ s c1 \4 _7 ~/ ]( L0 n# c4 u6 ]
8 a( T1 M( r: m7 V/ W7 ]/ }& e, w. {

产品名称

( G7 B% \. K1 ?: P o. o. ]7 X

SQL Server

+ q+ G, O6 ^4 U7 ^

产品版本

7 s' \% c u8 F* l# H! d0 |: [- x+ M, k

10.0

_" r$ D; l; u, _" S0 u, q! Y

产品内部版本号

: I9 z$ v/ q9 R- \$ P$ K( L

10.00.0000.00

8 w1 A+ x6 g$ c

事件 ID

8 G# k$ u v/ W, O: E! j I$ |

8651

) b0 R# Z+ I* c5 W0 n; l' j

事件源

( _. }4 C8 e0 T# p. w T- L9 `

MSSQLSERVER

$ g3 X" ]7 e; m1 J9 p1 v0 u$ P

组件

& Y# o+ Q1 f- O4 C& q N

SQLEngine

; {! D5 M3 h) A( y }

符号名称

7 h5 J" X4 V4 V

MEMGRANT_ERR

@* L2 z5 U3 n- e; _& X% M8 v

消息正文

( e0 z- ?2 q3 B4 h9 A, _# o

未能执行所请求的操作,因为可用内存少于最小查询内存。请减小“每次查询占用的最小内存”服务器配置选项的配置值。

- y9 P# Y" K I+ C) w2 ^ v0 y) N
; N, }7 e" t ~# v1 I, b, |; y+ g! }9 O5 O) G
7 |' ~3 ^+ W/ U( ]0 J

其他进程正在占用服务器内存(在服务器中施加内存压力)。

4 G7 o5 C$ r9 ^+ s3 E1 v& N
5 D% i9 g: W5 `0 G( F! K. T 8 h7 N" B, ?, Q6 ]1 F9 p* n
; G( U; Z$ |! t% B) ? _6 F/ i

减小“每次查询占用的最小内存”服务器配置选项的配置值,或者减少服务器的查询负载。

! ?7 j: ?. I/ c( M. j

下面的列表概述了有助于解决内存错误的一般步骤:

- b7 X4 Q8 l2 q$ A0 F' H: `+ \
    5 R9 |/ M/ B1 n U" l' V
  1. 验证其他应用程序或服务是否占用此服务器上的内存。重新配置不太重要的应用程序或服务,使其占用更少的内存。
    + |8 L( o: I e1 E! b1 F' `' t" P
  2. 开始收集 SQL Server: Buffer ManagerSQL Server: Memory Manager 的性能监视器计数器。
    1 }+ D* K4 W$ \; O
  3. 检查下面的 SQL Server 内存配置参数:
    ) a+ S% k# Z' }% j5 L7 }
      / f1 z z( W4 h& ]
    • max server memory
      ! F1 B7 c( q- y9 y3 M
    • min server memory
      + M% u8 B t0 z( O: T. ^; m& n( b
    • awe enabled
      7 j- d4 G% M% d) d0 a, z: M
    • min memory per query
    注意不正常的设置。根据需要将其更正。SQL Server 联机丛书中的“设置服务器配置选项”中列出了默认设置。
    6 L/ z# @& f2 L8 m
  4. 如果正在使用地址窗口化扩展插件 (AWE),请验证是否启用了 Windows 安全设置“锁定内存页”
    # m7 P" L; P+ }% v
  5. 检查工作负荷(例如,并发会话数,当前执行的查询)。
1 [0 _5 C! h$ h3 m1 @5 V

以下操作可以使更多内存可供 SQL Server 使用:

( L& G8 s3 Z8 U2 Q; y! L" d4 k
    * L; s5 {7 L! W1 t3 q4 Y' c
  • 如果除 SQL Server 外的应用程序正在占用资源,请尝试停止运行这些应用程序,或者考虑在单独的服务器上运行它们。这样做将消除外部内存压力。
    ! H* H/ S" [3 d) T
  • 如果已配置 max server memory,请增大其设置。
1 c6 t/ Q% G, Q Y) I, c( L9 D2 }

运行以下 DBCC 命令以释放几个 SQL Server 内存缓存。

8 l: f* [0 D" w( k' o
    ) A3 x D; Y- z2 \
  • DBCC FREESYSTEMCACHE
    ( h9 _7 F9 P1 g, a
  • DBCC FREESESSIONCACHE
    4 C7 x8 s" J G7 K* A1 ?
  • DBCC FREEPROCCACHE
) f1 G5 z* R8 v) V, i+ p4 I: k0 l

如果问题仍存在,则您将需要进一步调查,可能需要减小工作负荷。

 
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则


0关注

8粉丝

549帖子

排行榜
作者专栏

关注我们:微信订阅号

官方微信公众号

客服个人微信号

全国服务热线:

0595-22880819

公司地址:泉州秘途文化传媒有限公司

运营中心:福建省泉州市

Email:506070961#qq.com

Copyright   ©2015-2025  老秘网 责任编辑:释然Powered by©Discuz!技术支持:秘途文化  备案号   ( 闽ICP备19022590号-1 闽公网安备35050302000919号 )