T-SQL Recipes之Index Defragmentation
The Problem
索引一直是优化查询性能的不二法门。其中一个最直接的问题便是当审查一个低性能查询语句时,检查索引是否在正确的地方或者加索引没有。运行一个batchjob查看索引碎片,必要时采取步骤优化索引碎片是日常维护程序中不可缺少的。
今天的主题便是如何判定数据库中的索引碎片和优化措施
我们经常会用到sys.dm_db_index_physical_stats表来查看索引信息
示例:
USE AdventureWorks2014
GO DECLARE @database_name VARCHAR(100) = 'AdventureWorks2014';
SELECT SD.name AS database_name ,
SO.name AS object_name ,
SI.name AS index_name ,
IPS.index_type_desc ,
IPS.page_count ,
IPS.avg_fragmentation_in_percent
FROM sys.dm_db_index_physical_stats(NULL, NULL, NULL, NULL, NULL) IPS
INNER JOIN sys.databases SD ON SD.database_id = IPS.database_id
INNER JOIN sys.indexes SI ON SI.index_id = IPS.index_id
INNER JOIN sys.objects SO ON SO.object_id = SI.object_id
AND IPS.object_id = SO.object_id
WHERE alloc_unit_type_desc = 'IN_ROW_DATA'
AND index_level = 0
AND SD.name = @database_name
ORDER BY IPS.avg_fragmentation_in_percent DESC;
当知道索引碎片信息以后,我们应该如何优化呢?或者在任何数据库中查看索引碎片和优化呢?
The Solution
优化索引有两种方案
- Index Rebuild:
When an index is rebuilt , it is completely replaced with a new copy of the index, built from scratch as though
it were just newly created. In SQL Server Standard edition, this is an offline operation, meaning that it can
cause contention while running.- Index Reorganization:
Reorganizing an index results in cleanup at the leaf level, reordering pages and reapplying the fill factor as
necessary. This operation is always online, regardless of the edition of SQL Server you are running and can
be interrupted at any time with no ill effects.
现在我们通过百分比来判定索引是rebulid还是reorganization
IF OBJECT_ID('dbo.index_maintenance_demo','P') IS NOT NULL
BEGIN
DROP PROCEDURE dbo.index_maintenance_demo;
END
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE dbo.index_maintenance_demo
@reorganization_percentage TINYINT = 10 ,
@rebuild_percentage TINYINT = 35 ,
@print_results_only BIT = 1
AS
BEGIN
DECLARE @sql_command NVARCHAR(MAX) = '';
DECLARE @parameter_list NVARCHAR(MAX) = '@reorganization_percentage TINYINT, @rebuild_percentage TINYINT'
DECLARE @database_name NVARCHAR(MAX);
DECLARE @database_list TABLE
(
database_name NVARCHAR(MAX) NOT NULL
);
INSERT INTO @database_list
( database_name
)
SELECT name
FROM sys.databases
WHERE databases.name NOT IN ( 'msdb', 'master', 'TempDB',
'model','ReportServer$SQL2014' );
CREATE TABLE #index_maintenance
(
database_name NVARCHAR(MAX) ,
schema_name NVARCHAR(MAX) ,
object_name NVARCHAR(MAX) ,
index_name NVARCHAR(MAX) ,
index_type_desc NVARCHAR(MAX) ,
page_count BIGINT ,
avg_fragmentation_in_percent FLOAT ,
index_operation NVARCHAR(MAX)
);
SELECT @sql_command = @sql_command + '
USE [' + database_name + ']
INSERT INTO #index_maintenance
( database_name ,
schema_name ,
object_name ,
index_name ,
index_type_desc ,
page_count ,
avg_fragmentation_in_percent ,
index_operation
)
SELECT CAST(SD.name AS NVARCHAR(MAX)) AS database_name ,
CAST(SS.name AS NVARCHAR(MAX)) AS schema_name ,
CAST(SO.name AS NVARCHAR(MAX)) AS object_name ,
CAST(SI.name AS NVARCHAR(MAX)) AS index_name ,
IPS.index_type_desc ,
IPS.page_count ,
-- Be sure to filter as much as possible...this can return a lot of data if you dont filter by database and table.
IPS.avg_fragmentation_in_percent ,
CAST(CASE WHEN IPS.avg_fragmentation_in_percent >= @rebuild_percentage
THEN ''REBUILD''
WHEN IPS.avg_fragmentation_in_percent >= @reorganization_percentage
THEN ''REORGANIZE''
END AS NVARCHAR(MAX)) AS index_operation
FROM sys.dm_db_index_physical_stats(NULL, NULL, NULL, NULL, NULL) IPS
INNER JOIN sys.databases SD ON SD.database_id = IPS.database_id
INNER JOIN sys.indexes SI ON SI.index_id = IPS.index_id
INNER JOIN sys.objects SO ON SO.object_id = SI.object_id
AND IPS.object_id = SO.object_id
INNER JOIN sys.schemas SS ON SS.schema_id = SO.schema_id
WHERE alloc_unit_type_desc = ''IN_ROW_DATA''
AND index_level = 0
AND SD.name = ''' + database_name + '''
AND IPS.avg_fragmentation_in_percent >= @reorganization_percentage
AND SI.name IS NOT NULL -- Only review index, not heap data.
AND SO.is_ms_shipped = 0 -- Do not perform maintenance on system objects
ORDER BY SD.name ASC;'
FROM @database_list
WHERE database_name IN ( SELECT name FROM sys.databases );
EXEC sp_executesql @sql_command, @parameter_list,
@reorganization_percentage, @rebuild_percentage;
SELECT @sql_command = '';
SELECT @sql_command = @sql_command + '
USE ' + QUOTENAME(database_name) + '
ALTER INDEX ' + QUOTENAME(index_name) + ' ON ' + QUOTENAME(schema_name) + '.' + QUOTENAME(object_name) + ' '
+ index_operation + ';'
FROM #index_maintenance;
SELECT *
FROM #index_maintenance
ORDER BY avg_fragmentation_in_percent DESC;
IF @print_results_only = 1
BEGIN
PRINT @sql_command;
END
ELSE
BEGIN
EXEC sp_executesql @sql_command;
END
DROP TABLE #index_maintenance;
END
GO
然后运行SP得到以下结果
EXEC dbo.index_maintenance_demo @reorganization_percentage = 10, @rebuild_percentage = 35,
@print_results_only = 1;

打印出来的SQL如下:
USE [AdventureWorks2014]
ALTER INDEX [PK_ProductCostHistory_ProductID_StartDate] ON [Production].[ProductCostHistory] REBUILD;
USE [AdventureWorks2014]
ALTER INDEX [AK_ProductDescription_rowguid] ON [Production].[ProductDescription] REBUILD;
USE [AdventureWorks2014]
ALTER INDEX [PK_DatabaseLog_DatabaseLogID] ON [dbo].[DatabaseLog] REBUILD;
USE [AdventureWorks2014]
ALTER INDEX [PK_ProductInventory_ProductID_LocationID] ON [Production].[ProductInventory] REBUILD;
USE [AdventureWorks2014]
ALTER INDEX [PK_ProductListPriceHistory_ProductID_StartDate] ON [Production].[ProductListPriceHistory] REBUILD;
USE [AdventureWorks2014]
ALTER INDEX [PK_SpecialOfferProduct_SpecialOfferID_ProductID] ON [Sales].[SpecialOfferProduct] REBUILD;
USE [AdventureWorks2014]
ALTER INDEX [AK_SpecialOfferProduct_rowguid] ON [Sales].[SpecialOfferProduct] REBUILD;
USE [AdventureWorks2014]
ALTER INDEX [PK_StateProvince_StateProvinceID] ON [Person].[StateProvince] REBUILD;
USE [AdventureWorks2014]
ALTER INDEX [PK_ProductModelProductDescriptionCulture_ProductModelID_ProductDescriptionID_CultureID] ON [Production].[ProductModelProductDescriptionCulture] REBUILD;
USE [AdventureWorks2014]
ALTER INDEX [AK_BillOfMaterials_ProductAssemblyID_ComponentID_StartDate] ON [Production].[BillOfMaterials] REORGANIZE;
有了这个SP,以后我们的维护工作就轻便了许多。
T-SQL Recipes之Index Defragmentation的更多相关文章
- Caused by: java.sql.SQLException: Parameter index out of range (1 > number of parameters, which is 0
1.错误描述 [ERROR:]2015-05-05 16:35:50,664 [异常拦截] org.hibernate.exception.GenericJDBCException: error ex ...
- java.sql.SQLException:Column Index out of range,0<1
1.错误描述 java.sql.SQLException:Column Index out of range,0<1 2.错误原因 try { Class.forName("com.m ...
- java.sql.SQLException: Parameter index out of range (3 > number of parameters, which is 2).
java.sql.SQLException: Parameter index out of range (3 > number of parameters, which is 2). java. ...
- java.sql.SQLException: Parameter index out of range (1 > number of parameters, which is 0).
java.sql.SQLException: Parameter index out of range (1 > number of parameters, which is 0). at co ...
- java.io.IOException: java.sql.SQLException: ORA-01502: index 'BTO.PK_xxxxx' or partition of such index is in unusable state
最近由于数据库的全备出问题了,所以一直在观察. 刚好发现很多不需要的数据,就删了几百个G的数据吧. 今天突然就报这个问题. java.io.IOException: java.sql.SQLExcep ...
- sql server中index的REBUILD和REORGANIZE的区别及工作方式
sql server中index的REBUILD和REORGANIZE 转自:https://www.cnblogs.com/flysun0311/archive/2013/12/05/3459451 ...
- ylb:SQL 索引(Index)
ylbtech-SQL Server: SQL Server-SQL 索引(Index) SQL 索引(Index). ylb:索引(Index) 返回顶部 --=================== ...
- SQL Server 索引(index) 和 视图(view) 的简单介绍和操作
--索引(index)和视图(view)-- --索引(index)----概述: 数据库中的索引类似于书籍的目录,他以指针形式包含了表中一列或几列组合的新顺序,实现表中数据库的逻辑排序.索引创建在数 ...
- sql server中index的REBUILD和REORGANIZE
参考文献: http://technet.microsoft.com/en-us/library/ms188388.aspx 正文 本文主要讲解如何使用alter index来rebuild和reor ...
随机推荐
- Jquery制作--焦点图左右轮播
公司项目经常用到轮播焦点图,于是自己写了一个纯jq形式的横向轮播焦点图,可点击小圆点或者左右按钮进行切换,属于定宽类型.改成自适应宽度的也不难,将css里面的bannerCon宽度改为百分比,再在js ...
- mysql存储过程编写-入门案例-遁地龙卷风
(-1)写在前面 这篇文章只是简要的叙述了mysql存储过程编写的基本概念. 我使用的mysql版本是5.7.9-log. 参照<<深入浅出MySQL>>. (0) delim ...
- 卡特兰数(Catalan)
卡特兰数又称卡塔兰数,英文名Catalan number,是组合数学中一个常出现在各种计数问题中出现的数列.由以比利时的数学家欧仁·查理·卡塔兰 (1814–1894)命名,其前几项为 : 1, 2, ...
- ListView控件--2016年12月9日
ListView属性 ListView 名称 说明 AccessKey 重写 WebControl.AccessKey 属性. 不支持将此属性设置 ListView 控件.(覆盖 WebContr ...
- Android下LayoutInflater的使用
在我们想XML布局文件转换为View对象的时候.我们都会使用LayoutInflate对象.顾名思义咋一眼就能看出来他是布局填充器.那么接下来看看LayoutInfalte的使用 总体分为 Layou ...
- angular路由详解:
1.$routeProvider ngRoute模块中的服务 2.otherwise:设置用于路由改变时,与任何其他定义的路由无法匹配的时候执行的代码 3.when:为$route服务定义新的路由 例 ...
- 修改Firebug字体
Firebug是一件非常好用的调试工具,然而默认的字体有些单调,设置里又没有更改的选项,那么字体到底能不能更改呢?这个问题困扰了我好久,直到今天我才偶然发现了解决方案. Firebug属于火狐的一个插 ...
- python之路二十
一, $.ajax,这个是JQuery对ajax封装的最基础步,通过使用这个函数可以完成异步通讯的所有功能.也就是说什么情况下我们都可以通过此方法进行异步刷新的操作.但是它的参数较多,有的时候可能会麻 ...
- c#获取外网IP地址的方法
1.如果你是通过路由上网的,可以通过访问ip138之类的地址来获取外网IP 2.如果是通过PPPOE拨号上网的,可以使用以下代码获取IP //获取宽带连接(PPPOE拨号)的IP地址,timeout超 ...
- cf591d
题意:给出船的最大速度v,起点,终点.风在前t秒是一个方向,t秒后就一直是第二个方向.两个方向已知. 船速永远大于风速.问船在自由掌握速度和行驶方向的情况下,最快多久到终点. 分析:首先排除一种方法, ...