SQL SERVER整理索引碎片测试

SQL SERVER整理索引的方法也就这么几种,而且老是自作聪明的加入智能判断很不爽,还是比DBMS_ADVISOR差远了:

1SQL SERVER 2000/2005

查询

2000
use DB_Name
declare @table_id int
set @table_id=object_id('Table_Name')
dbcc showcontig(@table_id)

2005
SELECT index_id,index_type_desc,avg_fragmentation_in_percent,page_count 
FROM sys.dm_db_index_physical_stats(db_id(), OBJECT_ID('Table_Name'), NULL, NULL , 'LIMITED');

整理

2000
DBCC INDEXDEFRAG (DB_Name, 'dbo.Table_Name', Index_Name)
DBCC DBREINDEX ('DB_Name.dbo.Table_Name','',100)

2005
ALTER INDEX Index_Name ON dbo.Table_Name REBUILD

以下是一个网上找的不错的例子,链接是:
http://www.cnblogs.com/perfectdesign/archive/2008/02/20/sqlserverreindexrebuild.html
新建一个表:

create table t3
(
i int primary key,
xx varchar(200) not null
)

加入数据:

declare @x int
set @x = 0
while @x <1000
begin                       
insert into t3 values (@x,'qweasdqweasdqweasdqweqweasdqwe')
set @x = @x+1
end

执行动态管理视图:

SELECT index_id,index_type_desc,avg_fragmentation_in_percent,page_count 
FROM sys.dm_db_index_physical_stats
(db_id(), OBJECT_ID('t3'), NULL, NULL , 'LIMITED');

可以看到:

index_id为0表示这个是堆,平均的碎片有33%

现在执行几个可以减少碎片的方法都不管用,不能减少碎片。
包括:

DBCC INDEXDEFRAG (test, 'dbo.t3', PK__t3__0EA330E9)

alter index PK__t3__0EA330E9 on t3
rebuild

dbcc dbreindex ('t3')

这几个方法还有删除重建索引,都不能减少碎片数量。

后来我觉得是因为数据太少了,导致页也很少,数据库可能存在某种智能,判断是否值得去做重建索引的工作,所以加大的数据量:

declare @x int
set @x = 1000
while @x <10000
begin                       
insert into t3 values (@x,'qweasdqweasdqweasdqweqweasdqwe')
set @x = @x+1
end

再执行语句:

SELECT index_id,index_type_desc,avg_fragmentation_in_percent,page_count 
FROM sys.dm_db_index_physical_stats
(db_id(), OBJECT_ID('t3'), NULL, NULL , 'LIMITED');

alter index t3index on t3 rebuild

显示出来了!

结论:
SQL Server在执行相关的操作的时候都会智能去判断是否值得去做,比如在页面数太小的情况下可以不去重建索引,rebuild reindex 。类似的,在SQL Server 2005 里面也多了许多智能的判断来保证一个完整庞大而又不失智能的设计,
比如:
生成查询计划的阀值
缓存机制,缓存的筛选,LRU算法
预读机制
checkpoint减少回滚距离
智能join判断
重编译

了解SQL Server这种类似的软件产品能够为我们在设计产品的时候提供更多的思路想法,即使你了解上面的东西对你的SQL开发也不会有太多帮助。

另外附上几种方式的区别:
reindex是比较好的选择,速度快,但是他不能在线操作
INDEXDEFRAG 比较慢,但是可以在线操作
rebuild建议在碎片较少时采用。

附上微软的重建索引脚本,从里面也可以看出微软根据碎片大小推荐的方式,不过这个要随每个不同的数据库而定。

-- ensure a USE <databasename> statement has been executed first.
SET NOCOUNT ON;
DECLARE @objectid int;
DECLARE @indexid int;
DECLARE @partitioncount bigint;
DECLARE @schemaname sysname;
DECLARE @objectname sysname;
DECLARE @indexname sysname;
DECLARE @partitionnum bigint;
DECLARE @partitions bigint;
DECLARE @frag float;
DECLARE @command varchar(8000);
-- ensure the temporary table does not exist
IF EXISTS (SELECT name FROM sys.objects WHERE name = 'work_to_do')
    DROP TABLE work_to_do;
-- conditionally select from the function, converting object and index IDs to names.
SELECT
    object_id AS objectid,
    index_id AS indexid,
    partition_number AS partitionnum,
    avg_fragmentation_in_percent AS frag
INTO work_to_do
FROM sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL , NULL, 'LIMITED')
WHERE avg_fragmentation_in_percent > 10.0 AND index_id > 0;
-- Declare the cursor for the list of partitions to be processed.
DECLARE partitions CURSOR FOR SELECT * FROM work_to_do;

-- Open the cursor.
OPEN partitions;

-- Loop through the partitions.
FETCH NEXT
   FROM partitions
   INTO @objectid, @indexid, @partitionnum, @frag;

WHILE @@FETCH_STATUS = 0
    BEGIN;
        SELECT @objectname = o.name, @schemaname = s.name
        FROM sys.objects AS o
        JOIN sys.schemas as s ON s.schema_id = o.schema_id
        WHERE o.object_id = @objectid;

        SELECT @indexname = name 
        FROM sys.indexes
        WHERE  object_id = @objectid AND index_id = @indexid;

        SELECT @partitioncount = count (*) 
        FROM sys.partitions
        WHERE object_id = @objectid AND index_id = @indexid;

-- 30 is an arbitrary decision point at which to switch between reorganizing and rebuilding
IF @frag < 30.0
    BEGIN;
    SELECT @command = 'ALTER INDEX ' + @indexname + ' ON ' + @schemaname + '.' + @objectname + ' REORGANIZE';
    IF @partitioncount > 1
        SELECT @command = @command + ' PARTITION=' + CONVERT (CHAR, @partitionnum);
    EXEC (@command);
    END;

IF @frag >= 30.0
    BEGIN;
    SELECT @command = 'ALTER INDEX ' + @indexname +' ON ' + @schemaname + '.' + @objectname + ' REBUILD';
    IF @partitioncount > 1
        SELECT @command = @command + ' PARTITION=' + CONVERT (CHAR, @partitionnum);
    EXEC (@command);
    END;
PRINT 'Executed ' + @command;

FETCH NEXT FROM partitions INTO @objectid, @indexid, @partitionnum, @frag;
END;
-- Close and deallocate the cursor.
CLOSE partitions;
DEALLOCATE partitions;

-- drop the temporary table
IF EXISTS (SELECT name FROM sys.objects WHERE name = 'work_to_do')
    DROP TABLE work_to_do;
GO

BOL的推荐:

avg_fragmentation_in_percent 值 修复语句

> 5% 且 < = 30%

ALTER INDEX REORGANIZE

> 30%

ALTER INDEX REBUILD WITH (ONLINE = ON)*

小于5没必要重建,所以上面的SQL语句还是有得商量的地方。

http://blog.csdn.net/greenery/archive/2008/08/06/2778486.aspx

/**************************************
作用:在线整理索引碎片
时间:2008-5-15
说明:
          根据微软的示例改编
          适用于无法停机重建索引的情况,
          在线整理索引碎片,并更新表的统计信息以增强效果。
          另外可以自定义需要整理的索引的逻辑碎片程度,扫描密度,页数
          必须要在数据库访问较少的时候执行 
***************************************/
CREATE PROC [dbo].[SYS_IndexDrag]
AS
BEGIN

SET NOCOUNT ON
DECLARE @tablename VARCHAR (128)
DECLARE @execstr VARCHAR (255)
DECLARE @objectid INT
DECLARE @indexid INT
DECLARE @frag DECIMAL
DECLARE @maxfrag DECIMAL--逻辑碎片

DECLARE @MaxScanDensity DECIMAL--扫描密度

DECLARE @Page INT --8k页数,设定一个限度对一定大的索引进行整理

DECLARE @TmpName VARCHAR(150)

-- Decide on the maximum fragmentation to allow

SELECT @maxfrag = 30.0
SELECT @MaxScanDensity=70.0
SELECT @Page=400

-- Declare cursor

DECLARE tables CURSOR FOR
   SELECT TABLE_NAME
   FROM INFORMATION_SCHEMA.TABLES
   WHERE TABLE_TYPE = 'BASE TABLE'

-- Create the table

CREATE TABLE #fraglist (
   ObjectName CHAR (255),
   ObjectId INT,
   IndexName CHAR (255),
   IndexId INT,
   Lvl INT,
   CountPages INT,
   CountRows INT,
   MinRecSize INT,
   MaxRecSize INT,
   AvgRecSize INT,
   ForRecCount INT,
   Extents INT,
   ExtentSwitches INT,
   AvgFreeBytes INT,
   AvgPageDensity INT,
   ScanDensity DECIMAL,
   BestCount INT,
   ActualCount INT,
   LogicalFrag DECIMAL,
   ExtentFrag DECIMAL)

-- Open the cursor

OPEN tables

-- Loop through all the tables in the database

FETCH NEXT
   FROM tables
   INTO @tablename

WHILE @@FETCH_STATUS = 0
BEGIN
-- Do the showcontig of all indexes of the table

INSERT INTO #fraglist
   EXEC ('DBCC SHOWCONTIG (''' + @tablename + ''')
      WITH FAST, TABLERESULTS, ALL_INDEXES, NO_INFOMSGS')
    
   FETCH NEXT
      FROM tables
      INTO @tablename
END

-- Close and deallocate the cursor

CLOSE tables
DEALLOCATE tables

-- Declare cursor for list of indexes to be defragged

DECLARE indexes CURSOR FOR
   SELECT ObjectName, ObjectId, IndexId, LogicalFrag
   FROM #fraglist
   WHERE (LogicalFrag >= @maxfrag OR [ScanDensity]<=@MaxScanDensity) AND [CountPages]>=@page
      AND INDEXPROPERTY (ObjectId, IndexName, 'IndexDepth') > 0

-- Open the cursor

OPEN indexes

-- loop through the indexes

FETCH NEXT
   FROM indexes
   INTO @tablename, @objectid, @indexid, @frag

WHILE @@FETCH_STATUS = 0
BEGIN
  
   --在线整理碎片

PRINT 'Executing DBCC INDEXDEFRAG (0, ' + RTRIM(@tablename) + ',
      ' + RTRIM(@indexid) + ') - fragmentation currently '
       + RTRIM(CONVERT(varchar(15),@frag)) + '%'
   SELECT @execstr = 'DBCC INDEXDEFRAG (0, ' + RTRIM(@objectid) + ',
       ' + RTRIM(@indexid) + ')'
   EXEC (@execstr)
  
   --更新统计信息

IF @TmpName<>@tablename
   BEGIN
        SET @tmpName=@tableName
        EXEC('UPDATE STATISTICS '+@TableName) 
   END
    
   FETCH NEXT
      FROM indexes
      INTO @tablename, @objectid, @indexid, @frag
END

-- Close and deallocate the cursor

CLOSE indexes
DEALLOCATE indexes

-- Delete the temporary table

DROP TABLE #fraglist

END

GO

[转]SQL SERVER整理索引碎片测试的更多相关文章

  1. sql server 表索引碎片处理

    DBCC SHOWCONTIG (Transact-SQL) SQL Server 2005 其他版本 更新日期: 2007 年 9 月 15 日 显示指定的表或视图的数据和索引的碎片信息. 重要提示 ...

  2. sql server 查看索引碎片大小,并定期重建索引

      查看碎片情况使用  dbcc showcontig 函数来进行 代码: --改成当前库 use DB_Name --创建变量 指定要查看的表 declare @table_id int set @ ...

  3. 改进SQL Server 性能 - 索引碎片重建

    我们先来看一个用户表上的索引碎片情况: DBCC SHOWCONTIG scanning 'Lead' table...Table: 'Lead' (1422628111); index ID: 1, ...

  4. SQL Server清理索引碎片

    DECLARE @SchemeName NVARCHAR(MAX)=N''; DECLARE @TableName NVARCHAR(MAX)=N''; DECLARE @IndexName NVAR ...

  5. 提升SQL Server速度整理索引碎片

    转载:http://wenku.baidu.com/view/f64c8a707fd5360cba1adbea.html SQL Server2005索引碎片分析和解决方法   毫无疑问,给表添加索引 ...

  6. SQL Server通过整理索引碎片和重建索引提高速度

    本文章转载:http://database.51cto.com/art/201108/282408.htm SQL Server数据库中,当索引碎片太多时,就会拖慢数据库查询的速度.这时我们可以通过整 ...

  7. [转]整理索引碎片,提升SQL Server速度

    数据库表A有十万条记录,查询速度本来还可以,但导入一千条数据后,问题出现了.当选择的数据在原十万条记录之间时,速度还是挺快的:但当选择的数据在这一千条数据之间时,速度变得奇慢. 凭经验,这是索引碎片问 ...

  8. SQL Server 查询优化 索引的结构与分类

    一.索引的结构 关系型数据库中以二维表来表达关系模型,表中的数据以页的形式存储在磁盘上,在SQL SERVER中,数据页是磁盘上8k的连续空间,那么,一个表的所有数据页在磁盘上是如何组织的呢?分两种情 ...

  9. SQL Server-索引管理

    http://www.2cto.com/database/201305/207508.html SQL Server-索引管理   一.显示索引信息 在建立索引后,可以对表索引信息进行查询. (1)在 ...

随机推荐

  1. 38.Spring-spring和hibernate整合.md

    目录 1.定义各种类对象 2.创建Hibernate配置文件 3.配置applicationContext.xml 4.注意事项 1.定义各种类对象 package per.liyue.sh.demo ...

  2. 记账本,C,Github,Dao

    package dao; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSe ...

  3. WMS接口平台配置培训

    供应链管理平台地址:https://twms.ninestargroup.com/ibus/#/processconfig?scShortcutld=3_17__1_303 WMS提供WSWMS固定的 ...

  4. df -i 100%时处理方法

    晚上正在看文档的时候,运营突然打电话给我说游戏全炸了,都玩不了了: 我立马登上服务器,查看了下各服务是否正常运行,结果运行命令都报Unable to create lock file:  No spa ...

  5. spring mvc重定向

    spring mvc重定向有三种方法. 1.return new ModelAndView("redirect:/toUrl"); 其中/toUrlt是你要重定向的url. 2.r ...

  6. 365. Water and Jug Problem量杯灌水问题

    [抄题]: 简而言之:只能对 杯子中全部的水/容量-杯子中全部的水进行操作 You are given two jugs with capacities x and y litres. There i ...

  7. 491. Increasing Subsequences增长型序列

    [抄题]: Given an integer array, your task is to find all the different possible increasing subsequence ...

  8. WebApi上传文件

    上网搜了下Web Api上传文件的功能,发现都写的好麻烦,就自己写了一个,比较简单,直接上传文件就可以,可以用Postman测试. 简单的举例 /// <summary> /// 超级简单 ...

  9. 使用手势对UIImageView进行缩放、旋转和移动

    // 添加所有的手势 - (void) addGestureRecognizerToView:(UIView *)view { // 旋转手势 UIRotationGestureRecognizer  ...

  10. zeromq学习记录(七)订阅发布消息封装

    之前也有提到 使用订阅发布 pub sub模式必须要显示定义ZMQ_SUBSCRIBE 只有以此模式定义的过滤字节开头的消息才会被订阅者收到 如果想收到所有信息 可定义subscriber.setso ...