B-Tree có được cân bằng lại trong quá trình xóa dữ liệu khỏi bảng SQL Server với một chỉ mục được nhóm không?


10

Tôi có một bảng trong cơ sở dữ liệu SQL Server với chỉ mục được nhóm trên khóa chính. Bảng có 1 triệu hàng. Nếu tôi xóa 10K hàng khỏi bảng, chỉ mục có được cấu trúc lại trong khi thao tác xóa được thực hiện không?

Các hoạt động xóa là một phần của thủ tục lưu trữ. Tại một thời điểm, nhiều khách hàng có thể thực hiện thủ tục được lưu trữ, tuy nhiên mỗi lần chạy riêng lẻ sẽ xóa tập hợp hàng riêng của nó (được xác định duy nhất bởi khóa chính). Tôi đang bị khóa trên Khóa khóa (loại U) khi nhiều khách hàng thực hiện quy trình. Khóa chặn thuộc về một hàng trong cùng một bảng và nó không phải là một phần của bất kỳ giao dịch nào đang chạy đồng thời. Không nên có bất kỳ sự chặn nào vì mỗi lần chạy đang cố xóa tập hợp các hàng của chính nó. Khóa leo thang không xảy ra khi nó bị tắt.

Tôi nghi ngờ, thao tác xóa phải khiến chỉ số cân bằng lại và do đó trong quá trình tái cấu trúc, nó có thể khóa phím trên bất kỳ hàng nào của bảng.

Tôi thực sự sẽ đánh giá cao bất kỳ ý kiến ​​về điều này.


Câu hỏi hay và đoán hay. Có, khi bạn xóa bản ghi, chỉ mục được xây dựng lại. Trong quá trình xây dựng lại bảng quy trình là khóa và người dùng khác sẽ không thể truy cập vào bảng đó. stackoverflow.com/questions/6309614/
hy

4
KHÔNG, xóa các hàng trên chỉ mục cụm không gây ra xây dựng lại chỉ mục. Bạn cũng có thể gửi truy vấn được sử dụng để xóa dữ liệu. Khóa U xuất hiện khi truy vấn đang cố gắng tìm dữ liệu sẽ bị xóa và cuối cùng chỉ khóa các hàng để xóa nó.
Shanky

2
Khi xóa xảy ra, nó tạo ra một "lỗ hổng" hoặc bạn có thể nói khoảng trống khi dữ liệu đã bị xóa khỏi chỉ mục được nhóm. Điều này có thể tạo ra mật độ trang thấp và có thể được coi là một phân mảnh. Khi chèn xảy ra trên CI, nó sẽ điền vào các bản ghi ở bên phải và do đó, không gian có thể không bao giờ được lấp đầy. Nhưng SQL Server sẽ không tự động loại bỏ không gian này. Bạn phải xây dựng lại chỉ mục hoặc tổ chức lại để lấp đầy không gian này. KHÔNG có sự tái cân bằng như vậy
Shanky

1
@jayesh Tôi không thấy thứ tự các nút trong cây phải làm như thế nào với việc tái cân bằng. Cây B có thể bị mất cân bằng (do chèn hoặc xóa). Thứ tự nút không thay đổi trong những trường hợp này. Nó chỉ là một cái cây không cân đối.
ypercubeᵀᴹ

1
@jayesh Tôi nghĩ rằng bạn có thể có lợi khi đọc một số tài liệu MSSQL, vì tôi nghĩ thuật ngữ bạn đang sử dụng gây nhầm lẫn cho cả bạn và một số người trong chúng tôi.
LowlyDBA

Câu trả lời:


3

Để trả lời câu hỏi trong tiêu đề, liệu cây B có cân bằng lại trong khi xóa hay không, câu trả lời dường như là không, ít nhất là trong trường hợp thử nghiệm tối thiểu sau đây.

Bản demo sau đây chạy các lệnh còn lại tốt nhất cho môi trường thử nghiệm.

--create table and fill it
DROP TABLE IF EXISTS bunchesofints
CREATE TABLE bunchesofints (
thisisanint INT PRIMARY KEY CLUSTERED,
junkrow CHAR(1000) NOT NULL
)

INSERT dbo.bunchesofints
SELECT TOP 5000
ROW_NUMBER() OVER(ORDER BY(SELECT NULL)) AS thisisanint,
REPLICATE('a',1000) AS junkrow
FROM sys.all_objects a1
CROSS JOIN sys.all_objects a2


--with this query we can see all the non-leaf pages of the b-tree, plus the IAM
SELECT allocated_page_page_id, page_type_desc, page_level, is_allocated, next_page_page_id, previous_page_page_id
FROM sys.dm_db_database_page_allocations(DB_ID(),OBJECT_ID('dbo.bunchesofints'),NULL,NULL,'DETAILED')
WHERE page_type != 1
GO

--Ok, let's delete most of the rows
;WITH CTE AS (
    SELECT TOP (4500) *
    FROM dbo.bunchesofints
    ORDER BY thisisanint DESC
)

DELETE 
FROM CTE
GO

--Hmm, still have 3 non-leaf index pages
SELECT allocated_page_page_id, page_type_desc, page_level, is_allocated, next_page_page_id, previous_page_page_id
FROM sys.dm_db_database_page_allocations(DB_ID(),OBJECT_ID('dbo.bunchesofints'),NULL,NULL,'DETAILED')
WHERE page_type != 1



--So, where are the rows?
--please note the assumption that your test database has a single file.
DECLARE @firstindexpage INT, @lastindexpage INT, @db INT = DB_ID()
SELECT @firstindexpage = MIN(previous_page_page_id), @lastindexpage = MAX(next_page_page_id)
FROM sys.dm_db_database_page_allocations(DB_ID(),OBJECT_ID('dbo.bunchesofints'),NULL,NULL,'DETAILED')
WHERE page_type = 2 AND page_level = 1

DBCC PAGE(@db,1,@firstindexpage,3) WITH TABLERESULTS
DBCC PAGE(@db,1,@lastindexpage,3) WITH TABLERESULTS

Bản demo này cho thấy việc xóa có thể tạo ra một cây b rất mất cân bằng, thực tế là tất cả dữ liệu ở một bên.


cảm ơn vì lời giải thích rõ ràng và súc tích và mã demo. Tôi sẽ thử nó. Tôi sẽ chấp nhận câu trả lời này. Tôi vẫn đang cố gắng tìm hiểu tại sao xóa trên tập hợp các hàng khác nhau gây ra chặn trên bảng với chỉ mục được nhóm.
jayesh
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.