Các kịch bản sử dụng hợp lệ cho các bảng HEAP là gì?


31

Tôi hiện đang thực hiện một số nhập dữ liệu vào một hệ thống cũ và phát hiện ra rằng hệ thống này không sử dụng một chỉ mục cụm. Một tìm kiếm nhanh của Google đã giới thiệu cho tôi khái niệm về các bảng HEAP và bây giờ tôi tò mò về những kịch bản sử dụng nào mà bảng HEAP nên được ưu tiên hơn một bảng phân cụm?

Theo như tôi hiểu thì một bảng HEAP sẽ chỉ hữu ích cho các bảng kiểm toán và / hoặc khi việc chèn xảy ra thường xuyên hơn nhiều so với các lựa chọn. Nó sẽ tiết kiệm không gian đĩa và I / O đĩa vì không có chỉ số cụm để duy trì và sự phân mảnh bổ sung sẽ không phải là vấn đề vì các lần đọc rất hiếm.


1
Bạn đang nói về SQL Server?
a_horse_with_no_name

@a_horse_with_no_name vâng, tôi đã quên đề cập đến việc đó
marc.d

Bảng heap phù hợp với các bảng có hàng triệu hàng bị người dùng đánh mạnh. Nhược điểm là chúng có thể chiếm rất nhiều dung lượng vì dữ liệu được lưu trữ vật lý chưa được sắp xếp. Ngoài ra, bạn dựa vào các chỉ mục của bạn để được điều chỉnh theo các truy vấn của bạn. Tôi đã làm việc ở những nơi hoàn toàn không sử dụng các chỉ mục cụm vì các vấn đề về hiệu suất. Có thể là do các lựa chọn chỉ mục cụm kém nhưng nếu bạn chỉ sử dụng bảng heap, bạn không phải lo lắng về điều đó. Một giải pháp tốt hơn là sử dụng phiên bản doanh nghiệp của máy chủ sql và phân vùng theo chiều ngang của bảng lớn. Nhưng nếu bạn không có ent


Câu trả lời:


22

Việc sử dụng hợp lệ duy nhất là cho

  • bảng phân tầng được sử dụng trong các quy trình nhập / xuất / ETL.
  • ad-hoc, sao lưu tạm thời và ngắn hạn của các bảng bằng cách sử dụng SELECT * INTO..

Các bảng phân tầng thường khá bằng phẳng và bị cắt trước / sau khi sử dụng.

Lưu ý rằng một chỉ mục được phân cụm thường nhỏ so với kích thước dữ liệu: dữ liệu mức thấp nhất của cấu trúc chỉ mục.

Bảng heap cũng có vấn đề. Ít nhất là

Cũng thấy


2
Nó thường sử dụng đống cho hai thứ riêng biệt. Bảng phân tầng và bảng làm việc của ETL mà tôi sử dụng để lưu trữ dữ liệu tạm thời khi bộ lớn để bảng tạm thời hoạt động hiệu quả. Tất cả đều được cắt ngắn ở lần tải tiếp theo.
Zane

Bằng cách này, câu hỏi hay.
Zane

1
Một điều chỉnh nhỏ - nếu bạn thực hiện CHỌN VÀO để tạo bản sao lưu nhanh của một bảng nhỏ trước khi bạn thực hiện thay đổi, một đống được tạo theo mặc định. Tôi muốn nói rằng đó là một cách sử dụng hợp lệ - nhưng đó chỉ là cách chọn nit. Tôi muốn thoát khỏi đống đó ngay khi tôi biết công việc của mình đã xong.
Brent Ozar

@BrentOzar: Đồng ý, tôi tự làm mọi lúc. Tinh thần của câu trả lời của tôi là "các bảng dài hạn và liên tục" nhưng tôi sẽ cập nhật
gbn

9

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 INTs 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.


5

Tôi nghĩ rằng việc sử dụng "hợp lệ duy nhất là dành cho các bảng phân tầng được sử dụng trong các quy trình nhập / xuất / ETL" là một hạn chế nhỏ để nói ít nhất. Bạn phải lấy một trường hợp sử dụng dự kiến ​​của một hệ thống nhất định và sau đó chọn dựa trên giá trị của các đống hoặc các bảng được sắp xếp chỉ mục (tôi biết, một thuật ngữ của Oracle nhưng nó mô tả nó một cách độc đáo).

Kho của chúng tôi tải ~ 1,5 tỷ hàng mỗi ngày và phải hỗ trợ ghi và xử lý đồng thời cao cũng như đọc. Cửa hàng quan hệ hỗ trợ cơ sở dữ liệu OLAP và do đó các lần đọc có xu hướng chủ yếu là quét bảng. Các báo cáo và nguồn cấp dữ liệu được tạo ra thường không đủ chọn lọc sao cho mọi chỉ mục đều hữu ích. Hệ thống hỗ trợ cửa sổ trượt dữ liệu và do đó, khi bảng được tải, chúng tôi hiếm khi ghi lại vào đó và đưa ra cách thực hiện phân vùng bảng khá kém yêu cầu khóa Sch-M để phân chia phân vùng, chuyển đổi và hợp nhất so với khóa Sch-S để đọc, v.v. , hệ thống phải sử dụng nhiều bảng, mặc dù chúng tôi cũng có một số bảng được phân vùng. Việc sử dụng nhiều bảng tạo điều kiện dễ dàng phân đoạn dữ liệu và chu trình dọn dẹp đồng thời cũng giảm sự tranh chấp.

Như vậy, chi phí được thêm vào của một bảng được tổ chức chỉ mục (bảng được nhóm) trên một số cột tùy ý so với việc có thể bcp thành một đống, xử lý các phân vùng OLAP, thực hiện một số truy vấn quét bảng và sau đó 3 ngày sau đó thả nó chỉ là không đáng Lưu ý rằng trong trường hợp của chúng tôi, dữ liệu quay trở lại từ cụm lưới lớn nên không có thứ tự nào cho dữ liệu, do đó, việc chèn vào bảng có chỉ mục cụm có thể đưa ra các vấn đề khác như "điểm nóng" và phân tách trang và tương tự.

Ngoài ra, tôi nghĩ rằng tranh luận về các trang bị phân tán là một chút không rõ ràng. Các chỉ mục được nhóm cũng có thể có các trang của chúng nằm rải rác trong tệp. Chỉ là sau khi lập chỉ mục lại (giả sử hơn 1000 trang), điều này có thể tốt hơn một đống nhưng sau đó bạn cũng phải lập chỉ mục lại.

Cũng có thể tiết kiệm không gian bằng cách sử dụng các cột thưa và nén nếu đó là một mối quan tâm. Đúng là trong một số trường hợp, việc chọn trên một bảng có chỉ mục được nhóm có thể nhanh hơn nhưng bạn phải cân nhắc điều đó với các tài nguyên cần thiết để tải nó và duy trì nó.

[Chỉnh sửa] Tôi có lẽ nên làm rõ rằng chỉ các bảng thực tế không được phân vùng của chúng tôi là đống. Tất cả các bảng được phân chia và bảng thứ nguyên đều có các chỉ mục được nhóm để hỗ trợ tra cứu hiệu quả, v.v ... [Edit2] Đã sửa 2,5 tỷ thành 1,5 tỷ. Tut, hai số đó nằm cạnh nhau. Điều gì xảy ra khi gõ phản hồi trên điện thoại tôi đoán ...

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.