码迷,mamicode.com
首页 > 数据库 > 详细

37. SQL -- 页分裂如何解决,在查询中强制使用索引

时间:2015-04-05 06:46:12      阅读:1273      评论:0      收藏:0      [点我收藏+]

标签:数据库   索引   页分裂   

页分裂:

创建聚集索引时,表格内的数据会按照索引的顺序存储在数据库的数据页面中,当新的数据行插入到数据表中,或更新表中的数据时,SQLServer 必须刷新数据在数据库中的存储位置,这样,就导致索引页中的数据存储方式改变,当页中数据已满的情况下,就将会创建一个新页,并将原有页中的一半数据放入新页中,以挪出空间给新的记录行使用。注:当页分裂的次数较多时,会影响效率.

 

导致页分裂原因:

当一个数据页达到了8K容量,如果此时发生插入或更新数据的操作,将导致页的分裂(又名页拆分):

有聚集索引的情况下:聚集索引将被插入和更新的行指向特定的页,该页由聚集索引关键字决定;

只有堆的情况下:只要有空间就可以插入新的行,但是如果我们对行数据的更新需要更多的空间,以致大于当前页的可用空间,行就被移到新的页中,并且在原位置留下一个转发指针,指向被移动的新行,如果具有转发指针的行又被移动了,那么原来的指针将重新指向新的位置;

如果堆中有非聚集索引,那么尽管插入和更新操作在堆中不会发生页分裂,但是在非聚集索引上仍然产生页分裂。无论有无索引,大约一半的数据将保留在老页面,而另一半将放入新页面,并且新页面可能被分配到任何可用的页。所以,频繁页分裂,后果很严重,将使物理表产生大量数

据碎片,导致直接造成I/O 效率的急剧下降,最后,不得不停止SQLS 的运行并重建索引。

解决方法:设置适当的填充因子

填充因子(fillfactor):

然而在―混沌之初‖,就可以在一定程度上避免不愉快出现,在创建索引时,可以为这个索引指定一个填充因子,以便在索引的每个叶级页面上保留一定百分比的空间,将来数据可以进行扩充和减少页分裂。填充因子是从0 到100 的百分比数值,设为100 时表示将数据页填满,只有当不会对数据进行更改时(例如只读表中)才用此设置。值越小则数据页上的空闲空间越大,这样可以减少在索引增长过程中进行页分裂的需要,但这一操作需要占用更多的硬盘空间。

例如,当填充因子的值为50 时,数据库的读取性能会降低两倍。所以,只有在表中根据现有数据创建新索引,并且可以预见将来会对这些数据进行哪些更改时,设置填充因子才有意义。

填充因子(Fillfactor):

指定 SQL Server存储索引数据时每个索引页的充满程度。用户指定的 fillfactor 取值范围从 1 到 100。

如果没有指定 fillfactor,则默认为0。

优点:减少了页面分裂的次数

缺点:增大了使用的存储空间

PAD_INDEX:

指定索引中间级中每个页上保持空闲的空间。PAD_INDEX 选项只有在指定了FILLFACTOR时才有用,因为PAD_INDEX 使用由 FILLFACTOR 所指定的百分比

语法:

CREATE NONCLUSTERED INDEX NI_TerminationReason_TerminationReason_DepartmentID

ON HumanResources.TerminationReason

(TerminationReason ASC, DepartmentID ASC)

WITH (PAD_INDEX=ON, FILLFACTOR=50)

语法格式:

Create index 索引名

On 表名(字段名)

With pad_index,fillfactor=n

注:各级索引页的填充程度为n

创建填充因子:

create index id_ha2_test

on tb_ha2(docno)

with pad_index ,fillfactor = 30

在创建填充因子和不创建填充因子占用磁盘空间对比:

A、 未创填充因子前的磁盘空间 :

sp_spaceused tb_ha2

name rows reserved data index_size unused

tb_ha2 5000 904 KB 848 KB 16 KB 40 KB

B、 创建普通索引磁盘空间:

create index id_ha2_test

on tb_ha2 (part)

sp_spaceused tb_ha2

name rows reserved dataindex_size unused

tb_ha2 5000 1552 KB 848 KB608 KB 96 KB

C、 创建填充因子后的磁盘空间:

create index id_ha2_test

on tb_ha2(docno)

with pad_index ,fillfactor = 30

sp_spaceused tb_ha2

name rows reserved data index_size unused

tb_ha2 5000 1808 KB 848 KB 832 KB 128 KB

DBCC showcontig (tb_ha2):查询索引页分页情况

 

重建索引:

数据库 → 表 → 索引 → 右键 → 全部重新生成

命令:

USE [demo_db]

GO

ALTER INDEX [PK__tb_ha2__0638335133D4B598]

ON [dbo].[tb_ha2]

REBUILD PARTITION = ALL

WITH

(

PAD_INDEX = OFF,

STATISTICS_NORECOMPUTE = OFF,

ALLOW_ROW_LOCKS = ON,

ALLOW_PAGE_LOCKS = ON,

ONLINE = OFF,

SORT_IN_TEMPDB = OFF,

DATA_COMPRESSION = NONE

)

GO

USE [demo_db]

GO

ALTER INDEX [id_ha2_test]

ON [dbo].[tb_ha2]

REBUILD PARTITION = ALL

WITH

(

PAD_INDEX = OFF,

STATISTICS_NORECOMPUTE = OFF,

ALLOW_ROW_LOCKS = ON,

ALLOW_PAGE_LOCKS = ON,

ONLINE = OFF,

SORT_IN_TEMPDB = OFF,

DATA_COMPRESSION = NONE

)

GO

重建索引:可减少请求数据所需的面数来提高性能.

n 在执行INSERT、UPDATE、DELETE 语句之后,会使得索引数据散乱在数据库存储空间内。

n 重建索引以优化索引结构

n DBCCDBREINDEX (表名,索引名,填充因子)

n 注:可减少请求数据所需的页数来提高性能

dbcc dbreindex(表名、索引名、真充因子)

dbcc dbreindex (tb_ha2)

DBCC showcontig (tb_ha2):查看索引分页情况:

 

当再次查入1000 条数据到tb_ha2 中:

insert into tb_ha2

values

(

LEFT (CONVERT(nvarchar(128),newid()),20),

left (convert(nvarchar(128),newid()),20)

)

go 1000

dbcc showcontig (tb_ha2):查看索引分页情况

 

在查询中强制使用索引

SQL Server 使用查询优化器选择执行查询的最佳方式 ,包括选择要使用的索引,查询优化器以页I/O 为标准,尝试选出成本最低的方法 。SQL Server 中可以强制查询优化器选择某个特定的索引。强制查询优化器选择某个特定的索引。

语法

(INDEX=index_name)

select * from tb_ha2

with (index = id_ha2_test)

where PART = ‘0021E3E7-D397-4FFF-A‘

查看显示预估的执行计划:

筛选索引:

筛选索引是一种经过优化的非聚集索引,尤其适用于涵盖从定义完善的数据子集中选择数据的查询。筛选索引使用筛选谓词对表中的部分行进行索引。与全表索引相比,设计良好的筛选索引可以提高查询性能、减少索引维护开销并可降低索引存储开销。

DEMO:

AdventureWorks 数据库中有一个包含 2679 行的 Production.BillOfMaterials 表。

EndDate 列只有 199 行包含非NULL 值,其余 2480 行均包含 NULL。下面的筛选索引将涵盖这样的查询:返回在此索引中定义的列的查询,以及只选择EndDate 值不为NULL 的行的查询。

USE AdventureWorks;

GO

IF EXISTS --在创建索引前,先查询此索引名称是否存在.若存在,则删除此索引

(

SELECT name

FROM sys.indexes

WHERE name = N‘FIBillOfMaterialsWithEndDate‘

AND object_id = OBJECT_ID (N‘Production.BillOfMaterials‘))

DROP INDEX FIBillOfMaterialsWithEndDate

ON Production.BillOfMaterials

GO

CREATE NONCLUSTERED INDEX FIBillOfMaterialsWithEndDate

ON Production.BillOfMaterials (ComponentID, StartDate)

WHERE EndDate IS NOT NULL;

GO


本文出自 “Ricky's Blog” 博客,请务必保留此出处http://57388.blog.51cto.com/47388/1628996

37. SQL -- 页分裂如何解决,在查询中强制使用索引

标签:数据库   索引   页分裂   

原文地址:http://57388.blog.51cto.com/47388/1628996

踩
(0)
赞
(0)
   
举报
评论 一句话评论(0)
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!