SqlServer索引碎片

1.产生碎片的操作

通过sys.dm_index_physical_stats来查看,索引上的页不在具有连续性时就会产生碎片,碎片是索引上页拆分的物理结果。

(1).插入操作:

INSERT操作在聚集索引和非聚集索引上都可以引起碎片

使用业务键或者GUID等类型 做聚集索引,很容易产生碎片

代码如下:

 IF OBJECT_ID(‘dbo.Table_GUID‘) IS NOT NULL
DROP TABLE dbo.Table_GUID;
CREATE TABLE Table_GUID
(
RowID UNIQUEIDENTIFIER CONSTRAINT DF_GUIDValue DEFAULT NEWID(),--使用GUID作为默认值
Name sysname,
Value VARCHAR(2000)
);

--插入数据,注意此时还没有创建聚集索引
INSERT INTO dbo.Table_GUID(  Name, Value )
		SELECT name,REPLICATE(‘X‘,2000)
		 FROM sys.columns

		 SELECT * FROM dbo.Table_GUID
--在列上创建聚集索引
CREATE CLUSTERED INDEX CLUS_UsingUniqueidentifer ON dbo.Table_GUID(RowID);

--查看平均碎片
SELECT index_type_desc,
index_depth,
index_level,
page_count,
record_count,
CAST(avg_fragmentation_in_percent AS DECIMAL(6,2)) AS avg_fragmentation_in_percent,
fragment_count,
avg_fragment_size_in_pages,
CAST(avg_page_space_used_in_percent AS DECIMAL(6,2)) AS avg_page_space_used_in_percent
 FROM sys.dm_db_index_physical_stats(DB_ID(),OBJECT_ID(N‘dbo.Table_GUID‘),NULL,NULL,‘DETAILED‘)

平均碎片为0,插入后才建索引。

插入数据:

 --插入新数据
 INSERT INTO dbo.Table_GUID
         (  Name, Value )
SELECT name, REPLICATE(‘X‘,2000) FROM sys.objects

查看索引碎片:

--查看平均碎片
SELECT index_type_desc,
index_depth,
index_level,
page_count,
record_count,
CAST(avg_fragmentation_in_percent AS DECIMAL(6,2)) AS avg_fragmentation_in_percent,
fragment_count,
avg_fragment_size_in_pages,
CAST(avg_page_space_used_in_percent AS DECIMAL(6,2)) AS avg_page_space_used_in_percent
 FROM sys.dm_db_index_physical_stats(DB_ID(),OBJECT_ID(N‘dbo.Table_GUID‘),NULL,NULL,‘DETAILED‘)

非聚集索引:

 CREATE NONCLUSTERED INDEX IX_Name ON dbo.Table_GUID(Name) INCLUDE(Value)

执行以上两次操作。

由此可见:当INSERT操作发生时,产生碎片再所难免,唯一要做的是尽可能降低碎片的产生速率。

(2):更新操作

 --跟新操作
  IF OBJECT_ID(‘dbo.Update_Fr‘) IS NOT NULL
DROP TABLE dbo.Update_Fr;
CREATE TABLE Update_Fr
(
RowID INT IDENTITY(1,1),--使用GUID作为默认值
Name sysname,
Value VARCHAR(2000)
);

INSERT INTO dbo.Update_Fr
        (  Name, Value )
		SELECT name,REPLICATE(‘X‘,1000)
 FROM sys.columns

 CREATE CLUSTERED INDEX CLUS_UsingUniqueidentifier ON dbo.Update_Fr(RowID);

 --检查一下空间
SELECT index_type_desc,
index_depth,
index_level,
page_count,
record_count,
CAST(avg_fragmentation_in_percent AS DECIMAL(6,2)) AS avg_fragmentation_in_percent,
fragment_count,
avg_fragment_size_in_pages,
CAST(avg_page_space_used_in_percent AS DECIMAL(6,2)) AS avg_page_space_used_in_percent
 FROM sys.dm_db_index_physical_stats(DB_ID(),OBJECT_ID(N‘dbo.Update_Fr‘),NULL,NULL,‘DETAILED‘)

--更新数据让长度变长
 UPDATE dbo.Update_Fr SET Value=REPLICATE(‘X‘,2000)
 WHERE RowID % 5=1

键值的改变导致碎片的产生:

 --创建一个非聚集索引
 CREATE NONCLUSTERED INDEX IX_Name ON dbo.Update_Fr(Name) INCLUDE (Value);

 --通过REVERST函数把名称反转监控跟新前后的碎片情况
SELECT index_type_desc,
index_depth,
index_level,
page_count,
record_count,
CAST(avg_fragmentation_in_percent AS DECIMAL(6,2)) AS avg_fragmentation_in_percent,
fragment_count,
avg_fragment_size_in_pages,
CAST(avg_page_space_used_in_percent AS DECIMAL(6,2)) AS avg_page_space_used_in_percent
 FROM sys.dm_db_index_physical_stats(DB_ID(),OBJECT_ID(N‘dbo.Update_Fr‘),NULL,NULL,‘DETAILED‘)

--通过REVERST函数把名称反转监控跟新前后的碎片情况

UPDATE dbo.Update_Fr
 SET Name=REVERSE(Name)
 WHERE RowID%9=1

 SELECT index_type_desc,
index_depth,
index_level,
page_count,
record_count,
CAST(avg_fragmentation_in_percent AS DECIMAL(6,2)) AS avg_fragmentation_in_percent,
fragment_count,
avg_fragment_size_in_pages,
CAST(avg_page_space_used_in_percent AS DECIMAL(6,2)) AS avg_page_space_used_in_percent
 FROM sys.dm_db_index_physical_stats(DB_ID(),OBJECT_ID(N‘dbo.Update_Fr‘),NULL,NULL,‘DETAILED‘)

(3).收缩操作:

 IF DB_ID(N‘Fragmentation‘) IS NOT NULL
 DROP DATABASE Fragmentation
 CREATE DATABASE Fragmentation
  USE Fragmentation

  IF OBJECT_ID(‘dbo.FirstTable‘) IS NOT NULL
DROP TABLE dbo.FirstTable;

CREATE TABLE dbo.FirstTable
(
RowID INT IDENTITY(1,1),
Name sysname,
Value VARCHAR(2000),
CONSTRAINT PK_FirstTable PRIMARY KEY CLUSTERED(RowID)
);

INSERT INTO dbo.FirstTable
        (  Name, Value )
SELECT name,REPLICATE(‘X‘,2000) FROM sys.columns

 IF OBJECT_ID(‘dbo.SecondTable‘) IS NOT NULL
DROP TABLE dbo.SecondTable;

CREATE TABLE dbo.SecondTable
(
RowID INT IDENTITY(1,1),
Name sysname,
Value VARCHAR(2000),
CONSTRAINT PK_SecondTable PRIMARY KEY CLUSTERED(RowID)
);

INSERT INTO dbo.SecondTable
        (  Name, Value )
SELECT name,REPLICATE(‘X‘,2000) FROM sys.columns

INSERT INTO dbo.FirstTable
        (  Name, Value )
SELECT name,REPLICATE(‘X‘,2000) FROM sys.columns

INSERT INTO dbo.SecondTable
        (  Name, Value )
SELECT name,REPLICATE(‘X‘,2000) FROM sys.columns

INSERT INTO dbo.FirstTable
        (  Name, Value )
SELECT name,REPLICATE(‘X‘,2000) FROM sys.columns

 SELECT index_type_desc,
index_depth,
index_level,
page_count,
record_count,
CAST(avg_fragmentation_in_percent AS DECIMAL(6,2)) AS avg_fragmentation_in_percent,
fragment_count,
avg_fragment_size_in_pages,
CAST(avg_page_space_used_in_percent AS DECIMAL(6,2)) AS avg_page_space_used_in_percent
 FROM sys.dm_db_index_physical_stats(DB_ID(),OBJECT_ID(N‘dbo.FirstTable‘),NULL,NULL,‘DETAILED‘)

 IF OBJECT_ID(‘dbo.SecondTable‘) IS NOT NULL
DROP TABLE dbo.SecondTable;

 SELECT index_type_desc,
index_depth,
index_level,
page_count,
record_count,
CAST(avg_fragmentation_in_percent AS DECIMAL(6,2)) AS avg_fragmentation_in_percent,
fragment_count,
avg_fragment_size_in_pages,
CAST(avg_page_space_used_in_percent AS DECIMAL(6,2)) AS avg_page_space_used_in_percent
 FROM sys.dm_db_index_physical_stats(DB_ID(),OBJECT_ID(N‘dbo.FirstTable‘),NULL,NULL,‘DETAILED‘)

删除前后的索引碎片一样。

由于SqlServer不会自动回收,调用DBCC SHRINKDATABASE来收缩数据库,再次查看碎片情况。

 DBCC SHRINKDATABASE(Fragmentation)

再次查看碎片:

所以自动收缩数据不建议使用。

时间: 2024-08-07 04:32:09

SqlServer索引碎片的相关文章

SQL Server2005索引碎片分析和解决方法

SQL Server2005索引碎片分析和解决方法 本文作者(郑贤娴),请您在阅读本文时尊重作者版权. 摘要: SQL Server,为了反应数据的更新,需要维护表上的索引,因而这些索引会形成碎片.根据工作量的特征,这些碎片会影响对应的工作性能.此文帮助决定是否需要整理碎片以改善性能的信息.SQL Serve提供一些命令来实现索引的碎片整理.这里比较其中两个命令:DBCC DBREINDEX 和 DBCC INDEXDEFRAG. 关键词: SQL Server;索引碎片;数据库优化毫无疑问,给

SQLSERVER 索引维护

SQLSERVER 索引维护 2012-03-08 00:30:09|  分类: 默认分类 |  标签:sql  sqlserver  索引  |举报|字号 订阅 Pages & Extents(页和扩展盘区)SQL Server 2000最基本的数据存储单元是data page,1个8K的存储空间.在分配存储空间时,SQL Server 2000并不是每次分配1个page,基本的存储空间分配单元是8个page的连续空间,称为extent.关于SQL Server 2000的page.exten

索引碎片整理(转)

索引碎片整理 一碎片种类 1 内部碎片,又称为平均页密度.是指索引正在占有超过它实际所需的空间大小. 它具有两面型:低百分比会对读取数据的查询产生负面影响,会涉及更多读取操作,因为如果页被填充满的话, 只需读取更少的页:另一方面,如果如果在创建索引时设置一个较低的填充因子,就可以避免当插入更多记录而不 必进行页拆分. 对应sys.dm_db_index_physical_stats的列avg_page_space_used_in_percent. 2 外部碎片,又称平均碎片百分比,或逻辑碎片.是

SQL Server数据库表索引碎片整理

在SQLServer数据库,通过DBCC ShowContig或DBCC ShowContig(表名)检查索引碎片情况,指导我们对其进行定时重建整理. 运行结果如下: 1 2 3 4 5 6 7 8 9 10 11 DBCC SHOWCONTIG 正在扫描 'tbModule' 表... 表: 'tbModule'(1845581613):索引 ID: 0,数据库 ID: 9 已执行 TABLE 级别的扫描. - 扫描页数.....................................

转:sql server索引碎片和解决方法

毫无疑问,给表添加索引是有好处的,你要做的大部分工作就是维护索引,在数据更改期间索引可能产生碎片,所以一些维护是必要的.碎片可能是你查询产生性能问题的来源. 那么到底什么是索引碎片呢?索引碎片实际上有2种形式:外部碎片和内部碎片.不管哪种碎片基本上都会影响索引内页的使用.这也许是因为页的逻辑顺序错误(即外部碎片)或每页存储的数据量少于数据页的容量(内部错误).无论索引产生了哪种类型的碎片,你都会因为它而面临查询的性能问题. 外部碎片 当 索引页不在逻辑顺序上时就会产生外部碎片.索引创建时,索引键

转:索引碎片(代码好像不可用,待修改)

创建索引是为了在检索数据时能够减少时间,提高检索效率.创建好了索引,并且所有索引都在工作,但性能却仍然不好,那很可能是产生了索引碎片,你需要进行索引碎片整理. 1.什么是索引碎片? 由于表上有过度地插入.修改和删除操作,索引页被分成多块就形成了索引碎片,如果索引碎片严重,那扫描索引的时间就会变长,甚至导致索引不可用,因此数据检索操作就慢下来了. 有两种类型的索引碎片:内部碎片和外部碎片. 内部碎片:为了有效的利用内存,使内存产生更少的碎片,要对内存分页,内存以页为单位来使用,最后一页往往装不满,

检测和整理索引碎片

索引碎片的检测和整理 存储数据是为了查找数据,存储结构影响数据查找的性能.对无序数据进行查找,最快的查找算法是哈希查找:对有序数据进行查找,最快的查找算法是平衡树查找.在传统的关系型数据库中,聚集索引和非聚集索引都是平衡树(B-Tree)类型的存储结构,用于顺序存储数据,便于实现数据的快速查找.除了提升数据查找的性能之外,索引还能减少硬盘IO和内存消耗.通常情况下,硬盘IO是查找性能的瓶颈,由于索引是数据表的列的子集,这意味着,索引只存储部分列的数据,占用的硬盘空间比全部列少了很多,因此,数据库

SqlServer索引及优化详解

(一)深入浅出理解索引结构 实际上,您可以把索引理解为一种特殊的目录.微软的SQL SERVER提供了两种索引:聚集索引(clustered index,也称聚类索引.簇集索引)和非聚集索引(nonclustered index,也称非聚类索引.非簇集索引).下面,我们举例来说明一下聚集索引和非聚集索引的区别: 其实,我们的汉语字典的正文本身就是一个聚集索引.比如,我们要查“安”字,就会很自然地翻开字典的前几页,因为“安”的拼音是“an”,而按照拼音排序汉字的字典是以英文字母“a”开头并以“z”

41.oracle索引,分析索引,索引碎片整理

概述 索引分为B树索引和位图索引.我们主要研究B树索引,B树索引如下图(图片源自网络): 索引是与表相关的一个可选结构,在逻辑上和物理上都独立于表数据,索引能优化查询,不能优化DML,oracle自动维护索引,频繁的DML操作反而会赢钱大量的索引卫华. 如果sql语句仅仅访问被索引的列,那么数据库只需从索引中读取数据,而不会读取表:如果该语句还要访问未被索引的列,那么数据库会使用rowid来查找表中的行,通常,为检索表数据,数据库以交换方式先读取索引块,然后读取对应的表. 索引的目的是减少IO