Tại sao cơ sở dữ liệu của tôi vẫn bị phân mảnh sau khi tôi xây dựng lại và giới thiệu lại mọi thứ?


41

Tôi có một cơ sở dữ liệu mà tôi đã cố gắng chống phân mảnh tất cả các bảng cùng một lúc bằng cách chạy T-SQL này:

SELECT 
        'ALTER INDEX all ON ' + name + ' REORGANIZE;' + CHAR(10) +
        'ALTER INDEX all ON ' + name + ' REBUILD;'
    FROM sys.tables

Và sau đó sao chép và dán đầu ra vào một cửa sổ truy vấn mới và chạy nó. Tôi không có lỗi, nhưng tôi vẫn có sự phân mảnh. Tôi đã thử chạy cả hai lệnh riêng biệt và vẫn có phân mảnh. Lưu ý: Tôi đã nhận thấy rằng REORGANIZEAaron không cần thiết và tôi biết rằng tôi có thể sử dụng sql động để tự động hóa việc này.

Tôi chạy cái này để xác định tôi vẫn bị phân mảnh:

SELECT * FROM 
sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL , NULL, NULL) 
WHERE avg_fragmentation_in_percent > 0

Và tôi đã nhận được:

database_id object_id   index_id    partition_number    index_type_desc alloc_unit_type_desc    index_depth index_level avg_fragmentation_in_percent    fragment_count  avg_fragment_size_in_pages  page_count  avg_page_space_used_in_percent  record_count    ghost_record_count  version_ghost_record_count  min_record_size_in_bytes    max_record_size_in_bytes    avg_record_size_in_bytes    forwarded_record_count  compressed_page_count
85  171147655   1   1   CLUSTERED INDEX IN_ROW_DATA 2   0   36.3636363636364    5   2.2 11  NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL
85  421576540   1   1   CLUSTERED INDEX IN_ROW_DATA 2   0   75  7   1.14285714285714    8   NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL
85  965578478   1   1   CLUSTERED INDEX IN_ROW_DATA 2   0   14.7058823529412    6   5.66666666666667    34  NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL
85  1061578820  1   1   CLUSTERED INDEX IN_ROW_DATA 2   0   40  4   1.25    5   NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL
85  1109578991  1   1   CLUSTERED INDEX IN_ROW_DATA 2   0   30.7692307692308    5   2.6 13  NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL
85  1205579333  2   1   NONCLUSTERED INDEX  IN_ROW_DATA 2   0   50  5   1.6 8   NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL
85  1493580359  1   1   CLUSTERED INDEX IN_ROW_DATA 2   0   50  6   1.66666666666667    10  NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL

Tôi biết tôi đang thiếu một cái gì đó thực sự cơ bản, nhưng tôi không biết cái gì.


Bạn đã mắc lỗi gì? Ngoài ra có một lý do bạn có nó tổ chức lại và xây dựng lại điều tương tự?
Shawn Melton

Shawn, tôi xin lỗi vì đã bỏ lỡ một từ. Tôi không có lỗi. Về lý do tại sao tôi chạy cả hai lệnh, tôi đã làm điều đó sau khi thử từng lệnh riêng lẻ. Tôi cập nhật câu hỏi của tôi.
Justin thân mến

Câu trả lời:


38

Những cái bàn nhỏ xíu. Số trang trong bảng của bạn là:

11, 8, 6, 5, 13, 8, 10

Họ chiếm tổng cộng 480kb. Có nghĩa đen là không có gì để chống phân mảnh.

Chỉnh sửa: Điều này đảm bảo một chút giải thích.

Một bảng hoặc chỉ mục mới thường được phân bổ 8 trang đầu tiên từ một mức độ hỗn hợp, thay vì thống nhất. Vì vậy, mỗi trang trong 8 trang đầu tiên có thể được phân bổ từ các phạm vi hỗn hợp khác nhau. Do đó, một bảng hoặc chỉ mục tiêu thụ 8 trang có thể có 8 đoạn, 1 trên mỗi 8 phạm vi hỗn hợp khác nhau.

Các tập lệnh chống phân mảnh được sử dụng rộng rãi hơn (một vài ví dụ được liên kết bên dưới) có xu hướng loại trừ các bảng nhỏ vì điều này. IIRC, <500 trang nằm trong một hoặc cả hai. Ở các kích thước này, có rất ít lợi ích cho việc chống phân mảnh và các số liệu phân mảnh có khả năng bị sai lệch bởi các phân bổ phạm vi hỗn hợp.


Ok, đó là thỏa đáng trừ khi người khác có câu trả lời tốt hơn tôi sẽ đánh dấu của bạn là chính xác.
Justin Dearing

3
+1 Đồng ý với Mark. Lo lắng về sự phân mảnh khi bạn thực sự có một số dữ liệu. :-)
Aaron Bertrand

Tôi hoàn toàn nắm bắt những gì bạn đang nói. Nhưng vì tò mò quá mức, có phải vì công cụ db không thể chống phân mảnh vài trang như vậy? Ý tôi là, phải có một lý do cho việc này.
Thomas Stringer

3
Không phải là nó không thể, nhưng tại sao nó lại làm phiền? Làm như vậy sẽ ít ảnh hưởng đến I / O - đặc biệt là vì các bảng nhỏ này hầu như được đảm bảo trong bộ nhớ.
Aaron Bertrand

1
Chỉ. Có vẻ kỳ lạ, đó là tất cả. Giả sử tôi đang viết một ứng dụng để kiểm tra và báo cáo về phân mảnh chỉ mục, tôi sẽ phải thêm logic quảng cáo để không chỉ kiểm tra tỷ lệ phần trăm mà còn cả số lượng trang để không có báo động sai.
Thomas Stringer

19

Trích dẫn từ " Thực tiễn tốt nhất về phân mảnh chỉ số Microsoft SQL Server 2000 ":

"Phân mảnh ảnh hưởng đến I / O của đĩa. Do đó, hãy tập trung vào các chỉ mục lớn hơn vì các trang của chúng ít được lưu trữ bởi SQL Server. Sử dụng số trang được báo cáo bởi DBCC SHOWCONTIG để có ý tưởng về kích thước của các chỉ mục (mỗi trang là Kích thước 8 KB) Nói chung, bạn không nên quan tâm đến các mức phân mảnh của các chỉ mục có ít hơn 1.000 trang. Trong các thử nghiệm, các chỉ mục chứa hơn 10.000 trang nhận ra hiệu suất tăng, với mức tăng lớn nhất trên các chỉ mục có nhiều trang hơn (lớn hơn hơn 50.000 trang) . "

Vì vậy, loại câu trả lời này cho câu hỏi của bạn và ủng hộ câu trả lời của Mark và Aaron.

Bạn có thể tìm thấy thông tin tốt về phân mảnh chỉ mục trong các bài viết sau từ Brent Ozar:

Ngoài ra..một loạt thông tin tuyệt vời về các chỉ mục nói chung (cũng về các vấn đề phân mảnh) có thể được tìm thấy trên blog của Kimberly Tripp .


12

Điều này không có nghĩa là để trả lời câu hỏi của bạn, nhưng nó sẽ không bao giờ phù hợp với một bình luận. Bạn có thể xây dựng tập lệnh này một cách linh hoạt mà không cần phải sao chép và dán đầu ra vào một cửa sổ khác. Có tính đến việc hoàn toàn không có lý do REORGANIZEvà sau đó REBUILD:

DECLARE @sql NVARCHAR(MAX) = N'';

SELECT @sql += N'ALTER INDEX all ON ' + name + ' REBUILD;
    ' FROM sys.tables;

PRINT @sql; -- to see the first 8,000 characters and make sure it checks out
-- EXEC sp_executesql @sql;

Aaron, cảm ơn vì đã chỉ ra sql động, tôi biết rõ về sql động, tôi sẽ không tự động hóa giải pháp cho đến khi nó hoạt động. Những người khác đọc điều này có lẽ nên được nhận thức mặc dù.
Justin Dearing
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.