Làm cách nào để giảm phân mảnh HEAP trong SQL Server?


10

tôi gần đây đã phát hiện ra rằng một bảng heap có sự phân mảnh hơn 70%. Vì vậy, tôi quyết định làm một

ALTER TABLE dbo.myTable REBUILD

Hài hước lắm, sau đó tôi đã phân mảnh 20%. Không có chữ viết trên bàn kể từ đó. Vì vậy, tôi quyết định làm lại một lần nữa.

Sau lần thứ 2 mũ bàn phân mảnh 50% nên còn hơn thế nữa! Tôi thực sự không hiểu làm thế nào điều này có thể xảy ra ...


Bạn có ý nghĩa gì khi nói phân mảnh hợp lý. Đó là sự phân mảnh về mặt sử dụng của các trang dữ liệu. Tôi biết không có thứ tự nhưng dữ liệu không có thứ tự không bị phân mảnh. Phân mảnh trong trường hợp này có nghĩa là sử dụng hiệu quả các trang dữ liệu.
tuxmania

2
Tôi đoán chúng ta nên hỏi, cái bàn to cỡ nào? Trong các hàng và trang.
Cody Konior

Câu trả lời:


17

Phân mảnh có nghĩa là gì trong một đống

Giá trị phân mảnh trong Heap mà bạn nhận được từ cột avg_fragmentation_in_percentbằng cách truy vấn sys.dm_db_index_physical_statscác trạng thái DMV

Phân mảnh logic cho các chỉ mục hoặc phân mảnh phạm vi cho các đống trong đơn vị phân bổ IN_law_DATA.

Hơn nữa BOL nói rằng

Đây là tỷ lệ phần trăm không theo thứ tự trong các trang lá của một đống. Phạm vi không theo thứ tự là một phạm vi mà phạm vi chứa trang hiện tại cho một heap không phải là phạm vi tiếp theo sau phạm vi chứa trang trước đó.

Vì vậy, bạn có thể thấy đó không phảikhông gian trống có trong các trang được phân bổ cho Heap mà là các chuỗi trang khác nhau tạo ra sự phân mảnh.

Điều này có thể được chứng minh bằng thử nghiệm nhỏ. Hãy để chúng tôi tạo Bảng Heap và chèn một số bản ghi vào đó và sau đó kiểm tra sự phân mảnh.

create table dbo.HeapTest
(
Id INT not NULL Default (1),
Col1   char(5000) Not null Default ('Heaps Are Cool')
)

SET NOCOUNT ON

Insert into dbo.Heaptest default values
go 50

select index_type_desc,avg_fragmentation_in_percent,fragment_count,
avg_page_space_used_in_percent,record_count
from sys.dm_db_index_physical_stats(db_id(),object_id('dbo.HeapTest','U'),0,default,'detailed')

Vì vậy, bảng Heap được tạo với 50 bản ghi trong đó. Dưới đây là sự phân mảnh trông như thế nào sau khi truy vấn DMV sys.dm_db_index_physical thống kê

nhập mô tả hình ảnh ở đây

Bạn có thể thấy avg_fragmentation_in_percentgiá trị cột là 33%. Bây giờ chúng ta hãy xem các trang được sắp xếp như thế nào. Điều này có thể được thực hiện bằng cách sử dụng truy vấn không có giấy tờ%%lockres%% . Các truy vấn sẽ là

SELECT  %%lockres%%, * FROM dbo.HeapTest;

Và dưới đây là những gì đầu ra trông như thế nào. Chỉ đính kèm phần có liên quan của nó. Truy vấn tạo ra 50 hàng kể từ khi chúng tôi chèn 50 hàng trong bảng dbo.HeapTest của chúng tôi.

nhập mô tả hình ảnh ở đây

Những gì nó nói là trang đầu tiên có ID 197, trang tiếp theo có ID Các 242trang tiếp theo có ID liên tục cho đến khi chúng tôi đạt được ID trang 264vì sau đó chúng tôi nhận được ID trang 280. Vì vậy, bước nhảy trong số ID trang này là những gì thực sự gây ra sự phân mảnh.

Bây giờ kẻo xây dựng lại heap và chạy lại lệnh để xem sự phân mảnh và cách các trang được sắp xếp. Chúng tôi nhận được phân mảnh như

nhập mô tả hình ảnh ở đây

Bạn có thể thấy sự phân mảnh là bây giờ 14%.

Hãy cho chúng tôi xem số trang được phân bổ

nhập mô tả hình ảnh ở đây

Chúng tôi chỉ có một bước nhảy còn lại tất cả các trang được phân bổ ID trang một cách thanh thản. Vì chỉ một phân đoạn nhảy giảm đáng kể.

Tôi xây dựng lại Heap một lần nữa và bây giờ khi tôi kiểm tra sự phân mảnh thì nó đã hoàn toàn biến mất. Và phân bổ ID trang giống như

nhập mô tả hình ảnh ở đây

Tại sao phân mảnh tăng

Bây giờ liên quan đến những gì có thể gây ra sự phân mảnh tăng lên, chúng ta có thể chứng thực rằng khi các trang được phân bổ cho heap chúng sẽ không liên tục, như bạn đã thấy ở trên, điều gì khiến giá trị phân mảnh tăng lên đã nhảy vào ID PAGE được phân bổ cho các trang.

Ở phía sau đầu bạn cũng nên nhớ rằng phân mảnh từ cho HEAP không có nghĩa gì, làm thế nào bạn xác định phân mảnh cho một loạt các trang không theo thứ tự.

Thực sự lo lắng về sự phân mảnh

Nếu bạn thực sự phải đối mặt với một kịch bản trong đó bảng heap bị phân mảnh và làm chậm các truy vấn, tốt hơn là tạo một chỉ mục được nhóm trên bảng hơn là xây dựng lại nó. Lý do là khi bạn xây dựng lại heap tất cả các chỉ mục Non Clustered cơ bản cũng được xây dựng lại khiến quá trình xây dựng lại mất nhiều thời gian hơn, sử dụng nhiều tài nguyên và nhật ký giao dịch đầy hơi. Trên một hệ thống sản xuất, người ta luôn cố gắng tránh điều này. Paul đã đề cập đến điều này trong mục Huyền thoại về đống .

PS: Vui lòng không sử dụng lệnh không có giấy tờ trên hệ thống sản xuất. Đây chỉ là để trình diễn.


Cảm ơn bạn đã phân tích chi tiết. Tôi đang phải đối mặt với các bảng heap lớn bởi vì một số người đam mê kho dữ liệu nghĩ rằng nó tốt hơn so với sử dụng Chỉ mục cụm nhưng sau đó họ sử dụng nhiều ràng buộc kiểm tra và các chỉ mục không được nhóm trên các đống đó vì vậy tôi không thực sự thấy được lợi ích của đống trong tình huống này. Tuy nhiên vì tôi chỉ là nhà phát triển ngu ngốc nên tôi phải đối phó với điều này. Cảm ơn một lần nữa cho cái nhìn sâu sắc :)
tuxmania

Làm thế nào để bạn chạy chọn index_type_desc, avg_frag sắc_in_percent, Fragment_count, avg_page_space_use_in_percent, record_count từ sys.dm_db_index_physical_stats (db_id (), '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' một bàn? nó trả về tất cả các chỉ mục trên tất cả các bảng cho tôi ngay cả khi tôi chính xác chỉ định tên bảng của mình trong 'object_id'
Mickael

@Mickael Tôi đã sử dụng hàm db_id () sẽ lấy cơ sở dữ liệu hiện tại và tôi đã đặt tên đối tượng cụ thể để nó sẽ luôn xem xét cơ sở dữ liệu hiện tại và tìm kiếm Heaptestvà đưa ra kết quả. Tôi chắc chắn bạn có thể đã bỏ lỡ một cái gì đó. Chỉ cần đảm bảo mức độ tương thích không phải là 80 trong trường hợp đó hàm db_id không hoạt động
Shanky

@Shanky tại sao bạn không khuyên bạn nên sử dụng truy vấn không có giấy tờ %% lockres %% trong sản xuất? Bạn có thể giải thích chi tiết không?
Ralph

@ user1624552 Đơn giản vì nó không có giấy tờ, có nghĩa là MS cũng không giữ tài liệu về nó được cập nhật. Hiệu ứng sau của nó là gì làm thế nào nó hoạt động không được ghi lại ở bất cứ đâu đó là lý do tại sao nó được yêu cầu như vậy. Ex có lệnh fn_dump_dblog () tạo lịch trình ẩn và điều đó không tốt. Lệnh này cũng không được hỗ trợ. Bạn có thể sử dụng nó nhưng rủi ro nằm ở bạn.
Shanky
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.