Tôi đã tạo bảng sau:
CREATE TABLE dbo.TestStructure
(
id INT NOT NULL,
filler1 CHAR(36) NOT NULL,
filler2 CHAR(216) NOT NULL
);
và sau đó tạo một chỉ mục cụm:
CREATE CLUSTERED INDEX idx_cl_id
ON dbo.TestStructure(id);
Tiếp theo tôi đã điền nó với 30 hàng mỗi kích thước là 256 byte (dựa trên khai báo bảng):
DECLARE @i AS int = 0;
WHILE @i < 30
BEGIN
SET @i = @i + 1;
INSERT INTO dbo.TestStructure (id, filler1, filler2)
VALUES (@i, 'a', 'b');
END;
Bây giờ dựa trên thông tin tôi đã đọc trong sách "Bộ công cụ đào tạo (Bài kiểm tra 70-461): Truy vấn Microsoft SQL Server 2012 (Itzik Ben-Gan)":
SQL Server tổ chức nội bộ dữ liệu trong một tệp dữ liệu trong các trang. Một trang là một đơn vị 8 KB và thuộc về một đối tượng; ví dụ, để một bảng hoặc một chỉ mục. Một trang là đơn vị nhỏ nhất của đọc và viết. Các trang được tiếp tục tổ chức thành phạm vi. Một phạm vi bao gồm tám trang liên tiếp. Các trang từ một phạm vi có thể thuộc về một đối tượng hoặc nhiều đối tượng. Nếu các trang thuộc về nhiều đối tượng, thì phạm vi được gọi là phạm vi hỗn hợp; nếu các trang thuộc về một đối tượng, thì phạm vi được gọi là phạm vi thống nhất. SQL Server lưu trữ tám trang đầu tiên của một đối tượng trong phạm vi hỗn hợp. Khi một đối tượng vượt quá tám trang, SQL Server sẽ phân bổ các phạm vi thống nhất bổ sung cho đối tượng này. Với tổ chức này, các vật thể nhỏ lãng phí ít không gian hơn và các vật thể lớn ít bị phân mảnh hơn.
Vì vậy, ở đây tôi có trang 8KB phạm vi hỗn hợp đầu tiên, được điền với 7680 byte (tôi đã chèn 30 lần hàng có kích thước 256 byte, vì vậy 30 * 256 = 7680), để kiểm tra kích thước tôi đã chạy kiểm tra kích thước Proc - nó trả về kết quả sau
index_type_desc: CLUSTERED INDEX
index_depth: 1
index_level: 0
page_count: 1
record_count: 30
avg_page_space_used_in_percent: 98.1961947121324
name : TestStructure
rows : 30
reserved : 16 KB
data : 8 KB
index_size : 8 KB
unused : 0 KB
Vì vậy, 16 KB được dành riêng cho bảng, trang 8 KB đầu tiên dành cho trang Root IAM, trang thứ hai dành cho trang lưu trữ dữ liệu lá có dung lượng 8KB với mức chiếm ~ 7,5 KB, bây giờ khi tôi chèn một hàng mới với 256 Byte:
INSERT INTO dbo.TestStructure (id, filler1, filler2)
VALUES (1, 'a', 'b');
nó không được lưu trong cùng một trang mặc dù nó có không gian 256 byte (7680 b + 256 = 7936 vẫn nhỏ hơn 8KB), một trang dữ liệu mới được tạo, nhưng hàng mới đó có thể vừa trên cùng một trang cũ , tại sao SQL Server tạo một trang mới khi nó có thể tiết kiệm không gian và thời gian tìm kiếm mua chèn nó vào trang hiện có?
Lưu ý: điều tương tự đang xảy ra trong chỉ số heap.