BOL dường như định nghĩa một đống là một bảng không có chỉ mục được nhóm.
Nhưng nhiều bài viết trực tuyến dường như đánh đồng một đống với một bảng mà không có bất kỳ loại chỉ mục nào.
Có bất kỳ sự tinh tế tôi không nhận thức được?
Cảm ơn
BOL dường như định nghĩa một đống là một bảng không có chỉ mục được nhóm.
Nhưng nhiều bài viết trực tuyến dường như đánh đồng một đống với một bảng mà không có bất kỳ loại chỉ mục nào.
Có bất kỳ sự tinh tế tôi không nhận thức được?
Cảm ơn
Câu trả lời:
Bạn cần phải rất cẩn thận những gì bạn đọc trên các interwebs ;-) (tất nhiên, điều đó cũng phù hợp với câu trả lời này hoặc khá nhiều thứ ở bất cứ đâu, nhưng vẫn còn). Cũng như có rất nhiều thông tin tốt ngoài kia, cũng có rất nhiều thông tin sai lệch (và đáng buồn thay, điều này không giới hạn thông tin kỹ thuật). Và mọi người sao chép và dán / đăng lại / chia sẻ cả hai. Vì vậy, thật tốt khi đặt câu hỏi :-).
Mặc dù BOL có một số sai lầm, trong trường hợp này (và hầu hết các trường hợp) đều đúng: Heap đặc biệt là một bảng không có chỉ mục Clustered. Nó không có gì để làm với các chỉ mục không cụm. Tất nhiên, đây có thể là một trường hợp đơn giản để hiểu sai những gì được nói trong các "bài đăng trực tuyến" này vì "một bảng không có bất kỳ loại chỉ mục nào" là một Heap, nhưng chỉ vì không có chỉ mục có nghĩa là không có chỉ mục Clustered. Tuy nhiên, nếu những bài đăng này cho rằng một bảng chỉ có các chỉ mục không được nhóm không phải là Heap, thì chúng chắc chắn sẽ không chính xác.
Nếu bạn nhìn vào sys.indexes
bạn sẽ thấy rằng index_id
các 1
là một Clustered Index và 0
là một Heap. Bảng sẽ có cái này hoặc cái kia. Không thể có cả hai. Các chỉ mục không phân cụm bắt đầu index_id
từ 2 và đi lên từ đó. Tất cả các bảng sẽ có index_id là 0
hoặc hoặc 1
tùy chọn một hoặc nhiều index_id
> = 2
.
Bạn thậm chí có thể kiểm tra điều này bằng cách sử dụng truy vấn sau:
SELECT COUNT(*)
FROM sys.indexes si
WHERE si.index_id IN (0, 1)
GROUP BY si.[object_id]
HAVING COUNT(*) > 1;
Nó sẽ không bao giờ trả lại một hàng.
Đây là một thử nghiệm thứ hai thậm chí còn rõ ràng hơn và không cho phép ai đó suy đoán rằng tình trạng này có thể tồn tại nhưng chỉ là không, mà tôi cho là có thể với thử nghiệm ở trên:
-- DROP TABLE #tmp;
CREATE TABLE #tmp (Col1 INT, Col2 INT);
SELECT * FROM tempdb.sys.indexes si WHERE si.[object_id] = OBJECT_ID(N'tempdb.dbo.#tmp')
-- 1 row; index_id = 0 and type_desc = HEAP
CREATE NONCLUSTERED INDEX [IX_#tmp] ON #tmp (Col2 ASC);
SELECT * FROM tempdb.sys.indexes si WHERE si.[object_id] = OBJECT_ID(N'tempdb.dbo.#tmp')
-- 2 rows; index_id = 0 / HEAP and index_id = 2 / NONCLUSTERED
CREATE CLUSTERED INDEX [CIX_#tmp] ON #tmp (Col1 ASC);
SELECT * FROM tempdb.sys.indexes si WHERE si.[object_id] = OBJECT_ID(N'tempdb.dbo.#tmp')
-- still 2 rows (not 3!!); index_id = 1 / CLUSTERED and index_id = 2 / NONCLUSTERED
Mục đích của thử nghiệm thứ hai này là các quyền trên là gì và là không đúng sự thật về SQL Server sẽ luôn luôn được SQL Server riêng của mình. Vì vậy, điều quan trọng là phải kiểm tra để hỏi SQL Server về câu hỏi chứ không phải con người. Ngay cả các chuyên gia đôi khi cũng sai, nhưng SQL Server luôn luôn đúng (tất nhiên liên quan đến câu hỏi về SQL Server).
Ngoài ra, mặc dù đây không phải là "bằng chứng" theo bất kỳ cách dứt khoát nào, tiêu đề của trang MSDN sau đây khá là:
Srutzky đã trả lời câu hỏi, nhưng đây là một kịch bản khác để tự kiểm tra:
CREATE TABLE TestForJohn
(TestID int)
CREATE INDEX IX_Test ON TestForJohn
(TestID)
SELECT t.name, i.type_desc
FROM sys.tables t
INNER JOIN sys.indexes i
ON t.object_id = i.object_id
WHERE t.name = 'TestForJohn'
DROP TABLE TestForJohn