1)看一下task manager, 如果Sql Server 占有的内存即使在服务器最忙得时候都不超过2GB, 而你有4GB内存,可以考虑在Windows boot.ini启动文件中加入 /3GB变量。这样SqlServer就可以使用3GB的内存,多1GB意味着更大的缓存,可以不用到Disk取频繁读取了
2) 运行Perfmon,
加入“Page Life Expectancy”如果这个值始终小于300秒,意味着你需要更大的内存,
加入“Buffer Cache hit ratio” 如果这个值小于90%,意味着你需要更大的内存.
加入 “Average Disk Queue length” 如果总是大于2,意味着磁盘操作需要排队完成。考虑升级存储设备
3)运行profiler,跟踪器
只选Stored procedure 和 T-Sql, 在Filter(过滤) tab, 选duration(时长)大于5000,这告诉跟踪器只捕捉运行时间超过5秒的程序。 你可以根据自己的情况调整这个变量。目的是找到制造麻烦的SQL.
4)运行sp_who2 ,看blk by 栏, 如果这栏不是空白, 有一个数字, 这就是造成阻塞(blocking)的线程id. 然后运行DBCC Inputbuffer(线程id), 你就可以看见这个线程在干什么。
5)确认你的客户端程序使用connection pooling,并在完成任务后关闭连接。Sqlserver默认255个连接,如果使用connection pooling, 这个值应该足够应付大多数情况。 如果你确认255不够,可以使用sp_configure重设这个值
6)以上都是在认为你完成数据库日常维护的前提下。 如果你不做日常维护,请立即开始。 经常用 DBCC indexDefrag. 每隔一段时间用DBCC DBREINDEX 重建 index. 你可以运行 DBCC Showcontig, 然后看Scan Density ,如果主要的大表Scan Density < 40%, 意味着你有严重的Fragmentation(碎片),该用DBCC REINDEX去整理了

 

DBCC SHOWCONTIG 执行后,结果全部类似下面片断
DBCC SHOWCONTIG 正在扫描 'sysobjects' 表...
表: 'sysobjects'(1);索引 ID: 1,数据库 ID: 12
已执行 TABLE 级别的扫描。
- 扫描页数.....................................: 586
- 扫描扩展盘区数...............................: 91
- 扩展盘区开关数...............................: 585
- 每个扩展盘区上的平均页数.....................: 6.4
- 扫描密度[最佳值:实际值]....................: 12.63%[74:586]
- 逻辑扫描碎片.................................: 47.27%
- 扩展盘区扫描碎片.............................: 97.80%
- 每页上的平均可用字节数.......................: 2209.8
- 平均页密度(完整)...........................: 72.70%
写了个类,用于从结果中挑出需要重建索引的表并生成sql语句

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
/**
* Read a file and print, using BufferedReader and System.out
*/
public class CatFile {
  public static void main(String[] av) {
    av = new String[1];
    av[0] = "e:\\DBCC Showcontig.TXT";
    CatFile c = new CatFile();
    if (av.length == 0) {
      c.process(new BufferedReader(new InputStreamReader(System.in)));
    }
    else {
      for (int i = 0; i < av.length; i++) {
        try {
          c.process(new BufferedReader(new FileReader(av)));
        }
        catch (FileNotFoundException e) {
          System.err.println(e);
        }
      }
    }
  }
  /** print one file, given an open BufferedReader */
  public void process(BufferedReader is) {
    try {
      String inputLine;
      String tableName = "";
      while ( (inputLine = is.readLine()) != null) {
        double density = 0;
        if (inputLine.indexOf("表: '" >= 0) {
          tableName = inputLine.substring(inputLine.indexOf("'" + 1,
                                          inputLine.indexOf("'(");
        }
        if (inputLine.indexOf("扫描密度" >= 0) {
          density = Double.parseDouble(inputLine.substring(inputLine.indexOf(
              "..: " + 4, inputLine.indexOf("%["));
          if (density <= 40.0) {
            //System.out.print("density--" + density);
            //System.out.print("    ";
            System.out.println("DBCC DBREINDEX (" + "'" + tableName +
                              "','',80)";
          }
        }
      }
      is.close();
    }
    catch (IOException e) {
      System.out.println("IOException: " + e);
    }
  }
}

 

 

回复:SQLServer I/O写入次数很高 CPU100%

1)你用不上AWE,因为你只有4G内存,32bit系统可以处理4G内存。 超过4G才需要激活AWE.
2)一般你应该对用户表进行DBCC SHOWCONTIG, 但你有几万个表,整理一下系统表的index碎片也许会有帮助。你可以 DBCC dbreindex你的sysobjects表。 扫描密度12.63%太低了。
3)看来你的系统主要以插入为主。你可以考虑作几件事情
a.看一下你的insert sql, 看能不能把尽可能多的insert,update 放到一个transaction里面,因为如果不这么做,每个insert都要commit,要求一个写操作到transaction log.-->I/O
b.如果可以,可以考虑simple recovery mode, 而不是 full recovery mode.可以减少transaction log i/o
c. 看一下你表的设置,index fill factor是什么值?如果你的表有频繁大量写入。可以考虑把 fill factor 设在70%左右。这样可以减少page split,同样减少IO消耗。
d.考虑把transactionlog 放在和数据不同的物理盘上
e.把你的10000张表归类,放在不同的文件组(file group)里,再把各个filegroup放到不同的物理盘上
d, e 需要升级你的存

 

 

回复:SQLServer I/O写入次数很高 CPU100%

但出从SQL的角度:
1。设置启动项的 /3GB,取消SQL的 enable awe,这样4GB的内存最多可以用到3GB,再安全策略里设置sql启动帐号(一般为system)的锁定内存的权限。
2。监控全表扫描是否很多,用profiler跟踪出耗IO的语句加以优化。
3。硬件的优化是有限度的,要分析是不是App造成的问题。
建议调整硬件设置的同时:
如果App是直接连到SQL的Server,建议改为三层,毕竟中间层可以帮数据库分压,串行化虽然让客户端慢点,但是可以保证服务器正常的数据处理,如此的IO很肉一搞挂硬盘的
我也是吓说,望高手指点。

 

 

回复:SQLServer I/O写入次数很高 CPU100%

1、我今天明白了一件事,从任务管理器看到的IO读取和写入是个累积值,不是当前正在发生的值,难怪会不停的增长
2、我们做了一次调整,数据库移到了一个新服务器上(windows2000 advanced server 内存有9G)
按照如下语句设置,

sp_configure 'show advanced options', 1
RECONFIGURE
GO
sp_configure 'awe enabled', 1
RECONFIGURE
GO
sp_configure 'max server memory', 4096
RECONFIGURE
GO


依然会收到15457异常提示--错误: 15457,严重度: 0,状态: 1
但从任务管理器看,sqlserver占用内存很小,不到100M,但是从曲线图看,内存总量用掉了4个多G,这台服务器上没有别的应用,我猜上面设置内存可能起作用了(难道要重启sqlserver吗)