大部分的锁极有可能是由于索引引起的。对于锁的分类我就不说了,网上说得很多。而索引分为聚集索引和非聚集索引。而对索引的操作有填充因子,这个可能对页面引起拆分。一旦有这样的操作将引发锁的问题。但无论你怎么进行设置都将会产生锁,除非你把索引去掉。但是我们不可能去掉索引,因为从这一方面,对性能无疑是有害的。

     现在说一下填充因子:创建索引时,可以指定一个填充因子,以便在索引的每个叶级页上留出额外的间隙和保留一定百分比的空间,供将来表的数据存储容量进行扩充和减少页拆分的可能性。填充因子的值是从   0   到   100   的百分比数值,指定在创建索引后对数据页的填充比例。值为   100   时表示页将填满,所留出的存储空间量最小。只有当不会对数据进行更改时(例如,在只读表中)才会使用此设置。值越小则数据页上的空闲空间越大,这样可以减少在索引增长过程中对数据页进行拆分的需要,但需要更多的存储空间。当表中数据会发生更改时,这种设置更为适当。
说明     即使对于一个面向许多插入和更新操作的应用程序来说,数据库读取次数一般也超过数据库写入次数的   5   到   10   倍。因此,指定一个不同于默认设置的填充因子会降低数据库的读取性能,而降低量与填充因子设置值成反比。例如,当填充因子的值为   50%   时,数据库的读取性能会降低两倍。

  从上面来看不难看出填充因子对性能有极大的影响。至于如何解决呢???一种办法就是不上锁(加nolock关键字)这样你就能提高服务器的性能。但从这一方面违背了数据的完整与稳定。如果你的应用程序不需要非常完整(特别是在门户网站下)加上nolock无疑是一个好的解决方案。之前我在北京面试一家公司,当时就说性能的优化,当时面试官说:查询不需要上锁,所以他认为这个对性能没有影响。而实际的经验告诉我,这个影响是非常显著的。曾经优化过一个高并发性的插入加上与不加影响性能百分之五十。

  好了,现在我也不废话了。拿个例子出来测试吧。

以下是创建测试数据库以极表:

 


代码 
  
IF       
    DB_ID 
    ( 
    ' 
    DeadlockDemo 
    ' 
    )  
    IS 
      
    NOT 
      
    NULL 
      
    DROP 
      
    DATABASE 
     DeadlockDemo
     GO 
    
     CREATE 
      
    DATABASE 
     DeadlockDemo
     GO 
    
     USE 
     DeadlockDemo
     GO 
    
     SET 
     NOCOUNT  
    ON 
    
     GO 
    
     IF 
      
    OBJECT_ID 
     ( 
    ' 
    BookmarkLookupDeadlock 
    ' 
    )  
    IS 
      
    NOT 
      
    NULL 
      
    DROP 
      
    TABLE 
     BookmarkLookupDeadlock
     IF 
      
    OBJECT_ID 
     ( 
    ' 
    BookmarkLookupSelect 
    ' 
    )  
    IS 
      
    NOT 
      
    NULL 
      
    DROP 
      
    PROC 
     BookmarkLookupSelect
     IF 
      
    OBJECT_ID 
     ( 
    ' 
    BookmarkLookupUpdate 
    ' 
    )  
    IS 
      
    NOT 
      
    NULL 
      
    DROP 
      
    PROC 
     BookmarkLookupUpdate
     GO 
    
     CREATE 
      
    TABLE 
     BookmarkLookupDeadlock (col1  
    int 
    , col2  
    int 
    , col3  
    int 
    , col4  
    char 
    ( 
    100 
    ))
     GO 
    
     DECLARE 
      
    @int 
      
    int 
    
     SET 
      
    @int 
      
    = 
      
    1 
    
     WHILE 
     ( 
    @int 
      
    <= 
      
    1000 
    )  
    BEGIN 
    
         INSERT 
      
    INTO 
     BookmarkLookupDeadlock  
    VALUES 
     ( 
    @int 
    * 
    2 
    ,  
    @int 
    * 
    2 
    ,  
    @int 
    * 
    2 
    ,  
    @int 
    * 
    2 
    )
         SET 
      
    @int 
      
    = 
      
    @int 
      
    + 
      
    1 
    
     END 
    
     GO 
    
     CREATE 
      
    CLUSTERED 
      
    INDEX 
     cidx_BookmarkLookupDeadlock  
    ON 
     BookmarkLookupDeadlock (col1)
     CREATE 
      
    NONCLUSTERED 
      
    INDEX 
     idx_BookmarkLookupDeadlock_col2  
    ON 
     BookmarkLookupDeadlock (col2)
     GO 
    
     CREATE 
      
    PROC 
     BookmarkLookupSelect  
    @col2 
      
    int 
      
    AS 
     
     BEGIN 
    
         SELECT 
     col2, col3  
    FROM 
     BookmarkLookupDeadlock  
    WHERE 
     col2  
    BETWEEN 
      
    @col2 
      
    AND 
      
    @col2 
    + 
    1 
    
     END 
    
     GO 
    
     CREATE 
      
    PROC 
     BookmarkLookupUpdate  
    @col2 
      
    int 
     
     AS 
    
     BEGIN 
    
         UPDATE 
     BookmarkLookupDeadlock  
    SET 
     col2  
    = 
     col2 
    + 
    1 
      
    WHERE 
     col1  
    = 
      
    @col2 
    
         UPDATE 
     BookmarkLookupDeadlock  
    SET 
     col2  
    = 
     col2 
    - 
    1 
      
    WHERE 
     col1  
    = 
      
    @col2 
    
     END 
    
     GO  
 
以下是从数据库读取的SQL代码:
 
     
代码   
USE      DeadlockDemo
     GO     
     SET      NOCOUNT  
    ON 
    
     IF       
    OBJECT_ID 
    ( 
    ' 
    tempdb..#t1 
    ' 
    )  
    IS 
      
    NOT 
      
    NULL 
    
     BEGIN      
         DROP       
    TABLE 
     #t1
     END     
     CREATE       
    TABLE 
     #t1 (col2  
    int 
    , col3  
    int 
    )
     GO     
     WHILE      ( 
    1 
    = 
    1 
    ) 
     BEGIN     
         INSERT       
    INTO 
     #t1  
    EXEC 
     BookmarkLookupSelect  
    4 
    
         TRUNCATE       
    TABLE 
     #t1
     END     
     GO       
 
以下是从数据库更新的代码:
  
USE     DeadlockDemo
    GO    
    SET     NOCOUNT  
   ON 
   
    WHILE     ( 
   1 
   = 
   1 
   ) 
    BEGIN    
        EXEC     BookmarkLookupUpdate  
   4 
   
    END    
    GO      
 
然后你执行测试一下,发现查询的代码将被kill掉,如果你去掉了非聚集索引idx_BookmarkLookupDeadlock_col2,则可顺利的进行,这说明非聚集索引对数据库的性能有极大的影响。
如果你执行以下SQL语句,再执行以上代码再测试一下:
 
  
alter         PROC 
    BookmarkLookupSelect  
   @col2 
     
   int 
     
   AS 
    
    BEGIN    
        SELECT     col2, col3  
   FROM 
    BookmarkLookupDeadlock(nolock)  
   WHERE 
    col2  
   BETWEEN 
     
   @col2 
     
   AND 
     
   @col2 
   + 
   1 
   
    END

 

你会发现一个结果,照常执行,从以上的测试对性能的优化可以得出以下几点:

去掉没有必要的索引

如果在业务允许的范围内,你可以加上nolock来提高性能,至于其它锁控制的关键字,大家也可以测试一下