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

分裂:

建聚集索引,表格内的数据会按照索引的序存在数据的数据面中,当新的数据行插入到数据表中,或更新表中的数据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 INSERTUPDATEDELETE 句之后,会使得索引数据散乱在数据内。

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

文章来自:http://57388.blog.51cto.com/47388/1628996
© 2021 jiaocheng.bubufx.com  联系我们
ICP备案:鲁ICP备09046678号-3