Những cân nhắc chính
Tôi thấy một lợi thế quan trọng đối với đống và một cho các bảng được nhóm, cộng với việc xem xét thứ ba có thể đi theo bất kỳ cách nào.
Một đống giúp bạn tiết kiệm một lớp không xác định. Các chỉ mục chứa ID hàng, trỏ trực tiếp (tốt, không thực sự, nhưng càng trực tiếp càng tốt) vào một vị trí đĩa. Do đó, một chỉ mục tìm kiếm trên một đống nên có giá khoảng một nửa chỉ mục không được tìm kiếm trong một bảng được nhóm.
Một chỉ mục được nhóm được sắp xếp, theo từng se, nhờ vào một chỉ mục (gần như) miễn phí. Bởi vì chỉ số phân cụm được phản ánh theo thứ tự vật lý của dữ liệu, nên nó chiếm ít không gian trên đầu dữ liệu thực tế, tất nhiên bạn phải lưu trữ bằng mọi cách. Bởi vì nó được sắp xếp theo thứ tự vật lý, một phạm vi quét theo chỉ số này có thể tìm đến điểm bắt đầu và sau đó nén dọc đến điểm cuối rất hiệu quả.
Các chỉ số trên các RID tham chiếu heaps, là 64 bit. Như đã đề cập, các chỉ mục không phân cụm trên bảng phân cụm tham chiếu khóa phân cụm, có thể nhỏ hơn (32 bit INT
), giống nhau (64 bit BIGINT
) hoặc lớn hơn (48 bit DATETIME2()
cộng với 32 bit INT
, hoặc GUID 128 bit). Rõ ràng một tài liệu tham khảo rộng hơn làm cho các chỉ số lớn hơn và đắt tiền hơn.
Yêu cầu không gian
Với hai bảng này:
CREATE TABLE TmpClustered
(
ID1 INT NOT NULL,
ID2 INT NOT NULL
)
ALTER TABLE TmpClustered ADD CONSTRAINT PK_Tmp1 PRIMARY KEY CLUSTERED (ID1)
CREATE UNIQUE INDEX UQ_Tmp1 ON TmpClustered (ID2)
CREATE TABLE TmpNonClustered
(
ID1 INT NOT NULL,
ID2 INT NOT NULL
)
ALTER TABLE TmpNonClustered ADD CONSTRAINT PK_Tmp2 PRIMARY KEY NONCLUSTERED (ID1)
CREATE UNIQUE INDEX UQ_Tmp2 ON TmpNonClustered (ID2)
... mỗi bản ghi có 8,7 M bản ghi, dung lượng cần thiết là 150 MB cho dữ liệu cho cả hai; 120 MB cho các chỉ mục của bảng được phân cụm, 310 MB cho các chỉ mục của bảng không được phân cụm. Điều này phản ánh rằng chỉ số phân cụm hẹp hơn RID và chỉ số phân cụm chủ yếu là "freebie". Không có các chỉ số duy nhất trên ID2
, không gian chỉ mục yêu cầu giảm xuống 155 MB cho bảng không phân cụm (một nửa, như bạn mong đợi) nhưng chỉ 150 KB cho PK phân cụm - gần như không có gì.
Vì vậy, một chỉ mục không được nhóm của một trường 32 bit trong một bảng được phân cụm với chỉ số 32 bit (tổng 64 bit, trên danh nghĩa) đã mất 120 MB, trong khi một chỉ mục của trường 32 bit trong một đống với 64 bit RID (tổng cộng 96 bit, trên danh nghĩa) mất 155 MB, ít hơn một chút so với mức tăng 50%, người ta có thể mong đợi một cách ngây thơ đi từ các khóa 64 bit đến 96 bit, nhưng tất nhiên có chi phí làm giảm sự khác biệt hiệu quả về kích thước.
Việc điền hai bảng và tạo các chỉ mục của chúng mất cùng thời gian cho mỗi bảng. Chạy các thử nghiệm đơn giản liên quan đến quét hoặc tìm kiếm, tôi thấy không có sự khác biệt về hiệu suất vật liệu giữa các bảng, phù hợp với giấy trắng của Microsoft mà gbn liên kết một cách hữu ích. Giấy nói không cho thấy một sự khác biệt đáng kể để truy cập đồng thời cao; Tôi không chắc tại sao điều đó xảy ra, hy vọng ai đó có nhiều kinh nghiệm hơn tôi với các hệ thống OLTP khối lượng lớn có thể cho chúng tôi biết.
Thêm ~ 40 byte dữ liệu độ dài biến ngẫu nhiên không thay đổi đáng kể sự tương đương này. Việc thay thế các INT
s bằng UUID rộng cũng không (mỗi bảng bị chậm lại ở cùng một mức độ). Số dặm của bạn có thể thay đổi, nhưng trong hầu hết các trường hợp, liệu chỉ số có sẵn có quan trọng hơn loại nào không.
Bit và miếng
Thực hiện quét phạm vi đối với chỉ mục không được phân cụm - vì bảng là một đống hoặc chỉ mục không phải là chỉ mục được phân cụm - liên quan đến việc quét chỉ mục và sau đó thực hiện tra cứu đối với bảng cho mỗi lần truy cập. Điều này có thể rất tốn kém, vì vậy đôi khi chỉ cần quét bảng. Bạn có thể làm việc xung quanh điều này với một chỉ số bao phủ, tuy nhiên. Điều này áp dụng cho dù bạn đã nhóm bảng của mình hay chưa.
Như @gbn đã chỉ ra, không có cách nào đơn giản để thu gọn một đống. Tuy nhiên, nếu bảng của bạn tăng dần theo thời gian - một trường hợp rất phổ biến - sẽ có ít lãng phí vì không gian được giải phóng bằng cách xóa sẽ được lấp đầy bởi dữ liệu mới.
Một số cuộc thảo luận giữa đống và so với bảng mà tôi đã thấy đưa ra một lập luận tò mò rằng một đống không có chỉ số thấp hơn một bảng được phân cụm trong đó nó luôn yêu cầu quét bảng. Điều này chắc chắn là đúng, nhưng so sánh có ý nghĩa hơn là "bảng phân cụm lớn được lập chỉ mục tốt" so với "đống lớn được lập chỉ mục tốt". Nếu bảng của bạn rất nhỏ hoặc bạn sẽ luôn thực hiện quét bảng, thì điều đó không quan trọng lắm nếu bạn gom nó hay không.
Bởi vì mỗi chỉ mục trong một bảng phân cụm tham chiếu chỉ mục phân cụm, chúng có hiệu lực trong tất cả các chỉ số bao trùm. Một truy vấn tham chiếu một cột được lập chỉ mục và (các) cột phân cụm có thể thực hiện quét chỉ mục mà không cần bất kỳ tra cứu bảng nào. Điều này thường không có giá trị nếu chỉ mục phân cụm của bạn là khóa tổng hợp, nhưng nếu đó là khóa doanh nghiệp mà bạn cần truy xuất bằng mọi cách thì đó là một tính năng hay.
TL; DR
Tôi là một người lưu trữ dữ liệu, không phải là chuyên gia OLTP. Đối với các bảng thực tế, tôi hầu như luôn sử dụng một chỉ mục phân cụm trên trường mà hầu như có thể cần quét phạm vi, điển hình là trường ngày. Đối với các bảng kích thước, tôi phân cụm trên PK để nó được đặt trước để hợp nhất tham gia vào các bảng thực tế.
Có một số lý do để sử dụng các chỉ số phân cụm, nhưng nếu không có lý do nào được áp dụng thì chi phí có thể không đáng giá. Tôi nghi ngờ có rất nhiều "chúng tôi luôn làm theo cách này" và "đó chỉ là cách thực hành tốt nhất" đằng sau những người sử dụng các chỉ mục được phân cụm trên toàn cầu. Hãy thử cả hai với bạn dữ liệu và bạn tải và xem những gì làm việc tốt nhất.