Một bảng sẽ có lợi nếu nó là một đống


7

Tôi có một bảng ghi nhật ký với khoảng 1.500.000 hàng, khóa chính là danh tính tăng dần và chỉ mục được nhóm nằm trên khóa chính. Giá trị nhận dạng được tạo tự động => bản ghi luôn được thêm vào cuối. Kích thước hàng trung bình là 1570 byte.

Có rất nhiều phân chia trang vì các hàng mới được thêm thường xuyên. Không có hàng nào nhận được cập nhật / xóa và có một chỉ mục không được nhóm trên bảng để các hàng có thể được chọn. Do sự phân tách trang, chỉ mục được phân cụm luôn bị phân mảnh> 65%.

Tôi tự hỏi bảng của tôi sẽ có lợi khi loại bỏ chỉ mục được nhóm và làm cho nó thành một bảng heap?

Đây là cách bảng của tôi + chỉ mục không phân cụm trông như sau:

CREATE TABLE [dbo].[LogEntry](
[Id] [bigint] IDENTITY(1,1) NOT NULL,
[Application] [varchar](20) NOT NULL,
[EntityFullName] [varchar](80) NOT NULL,
[Action] [int] NOT NULL,
[UserName] [varchar](25) NOT NULL,
[TimeStamp] [datetime] NOT NULL,
[EntityId] [varchar](50) NOT NULL,
[WhatChanged] [nvarchar](max) NULL,
CONSTRAINT [PK_LogEntry] PRIMARY KEY CLUSTERED(     
   [Id] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 100) ON [PRIMARY] ) 
ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]


CREATE NONCLUSTERED INDEX [ID_Application_Entity_FullName_TimeStamp] ON [dbo].[LogEntry]
(
    [Application] ASC,
    [EntityFullName] ASC,
    [TimeStamp] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = OFF) ON [PRIMARY]
GO

Cập nhật: Ai đó đã kích hoạt tự động thu nhỏ sau lưng tôi => đây sẽ là nguyên nhân của sự phân mảnh


Nếu không có nhiều lần quét và đọc xảy ra trên bảng này, bạn có thể xem xét việc lưu cột nvarchar (max) ngoài hàng. Tôi không chắc tại sao bạn lại bị phân mảnh mặc dù không có bản cập nhật. sp_tableoption N'MyTable ',' loại giá trị lớn ngoài hàng ',' BẬT '
Chad Mattox

Khi các mục nhật ký được thêm vào, chúng được thêm vào theo bó hoặc bởi các quy trình song song? Giá trị nhận dạng được tạo trước khi hàng được ghi vào đĩa và là nguyên nhân tiềm ẩn của sự phân mảnh.
Luôn luôn tảiData

Câu trả lời:


5

Điều này bắt đầu như một bình luận / câu hỏi nhưng nó đã kéo dài nên tôi đã chuyển nó ở đây:

Tôi thực sự bị ném bởi câu hỏi này. 1,5 triệu hàng không thực sự lớn như vậy. Và điểm đằng sau một bản sắc là nó ngày càng tăng. Nếu đó là CL của bạn, bạn không nên thực hiện chèn vào giữa trang, chắc chắn không đủ để gây ra mức độ phân mảnh mà bạn nhìn thấy.

Vài câu hỏi:

Bạn đang làm IDENTIY_INSERTS? Về cơ bản chỉ định giá trị nhận dạng nên là gì? Hoặc bạn đã thiết lập lại danh tính tại một số điểm để bạn đang chèn vào giữa phạm vi?

Thông thường nếu bạn đang thực hiện chèn thì nó trông như thế này:

5 6 7 8 < Next insert goes here >

Nhưng nếu bạn có một cái gì đó như thế này (giả sử giá trị nhận dạng tiếp theo của bạn là 4)

 1 2 3 < Next insert goes here > 100 101  

Sau đó, bạn có thể thấy khá nhiều chia tách trang. Nhưng trong quá trình bình thường của những điều bạn không nên.

Có bất kỳ cơ hội bạn đang thu hẹp cơ sở dữ liệu của bạn? Auto_shrinkhoặc một kế hoạch / công việc duy trì mà co lại? Nếu vậy, đó là sự thu hẹp gây ra sự phân mảnh của bạn không phải là chỉ số cụm.

Nói chung, không có gì sai với HEAP và chúng có thể nhanh hơn đối với INSERT. Mối quan tâm lớn nhất của tôi với họ có xu hướng là nếu bạn đang thực hiện một số lượng lớn các lần xóa hoặc cập nhật (mà bạn nói là bạn không). Trong những trường hợp đó, bạn có thể bị rò rỉ không gian và kết thúc với một bảng có kích thước nhiều GB nhưng có 0 hàng.

Câu trả lời thực tế

Cho rằng bạn có một tệp nhật ký và chỉ được chèn, bạn có thể thử thả PK và xem hiệu suất hoạt động như thế nào (dĩ nhiên là trong môi trường thử nghiệm). Khi bạn đã chạy một số thử nghiệm bằng cách sử dụng khối lượng công việc của mình và xem mọi thứ diễn ra như thế nào, hãy thay đổi sản xuất và theo dõi trong một thời gian. Bạn thậm chí có thể xem xét bỏ hoàn toàn cột danh tính.

Hãy kiểm tra điều đó mặc dù. Đó là một kẻ giết người.


Tôi tự hỏi nếu có một giá trị MAX trong cột Danh tính cao hơn giá trị nhận dạng được chèn cuối cùng? (Hiểu rằng tối đa, cao hơn và như vậy phụ thuộc vào những hạt giống và gia tăng trong quá khứ). Và tôi cũng với bạn về việc tôi không biết lý do để có PK đó trên bàn này, tất nhiên với rất nhiều giả định được đưa ra. Tôi cũng muốn nói rằng điều hợp thời trang cần làm là thậm chí không đặt loại dữ liệu này vào một bảng.
Karen Lopez

1
Nếu chỉ mục Clustered được tạo ra MÔ TẢ, thì các phần chèn sẽ liên tục ở đầu chỉ mục, điều này cũng có thể ảnh hưởng đến sự phân mảnh (??).
AMtwo

Cũng xin lưu ý rằng khi thực hiện từng INSERTs, Heaps không điền vào các trang của họ đầy đủ như các bảng Clustered làm. Và tôi đồng ý rằng một cái gì đó đang diễn ra ở đây không rõ ràng từ thông tin được cung cấp, vì vậy +1 để thúc đẩy điều tra trước khi tiến hành bất kỳ thay đổi nào :-).
Solomon Rutzky

1
@AMtwo Yep. Ví dụ về điều đó ở đây stackoverflow.com/questions/743858/ Kẻ
Martin Smith

1

Bạn có thể thấy thú vị khi kiểm tra Thomas Kejerser về các chỉ mục trong SQL Server. Mặc dù các chỉ mục cụm là rất hữu ích, có thể có lý do để giữ một đống. Ví dụ, đọc bài viết này:

http://kejser.org/clustered-indexes-vs-heaps/

Đặc biệt nhìn vào chủ đề: Các bảng dễ bị phân mảnh với nhiều hoạt động INSERT

Chủ đề này dường như mô tả chính xác vấn đề mà bạn đang phải đối mặt với sự phân mảnh. Vì thế...

Hãy xem xét lựa chọn thay thế: một chiến lược lập chỉ mục trong đó bạn chọn một khóa ngẫu nhiên đầy đủ (như GUID) và thay vì khai báo một cách mù quáng khóa đó là một chỉ mục cụm , thay vào đó, bạn rời khỏi bảng như một đống và chỉ đặt một thứ độc đáo kiểu cũ, không chỉ số khóa được bao gồm trên GUID . Phần lớn sự tăng trưởng của bảng từ INSERT hiện đang chuyển sang heap, nó sẽ lấp đầy và không bị phân mảnh.

Một nhận xét khác từ Technet: http://technet.microsoft.com/en-us/l Library / hh213609.aspx

"Đôi khi các kiến ​​trúc sư dữ liệu sử dụng heaps khi dữ liệu luôn được truy cập thông qua các chỉ mục không được bao gồm và RID nhỏ hơn một khóa chỉ mục được nhóm."

Những bài viết có thể cung cấp cho bạn một cái gì đó để suy nghĩ về vấn đề của bạn.


3
Điều thú vị là @aaronbertrand đã thực hiện một bài kiểm tra tốc độ về loại bỏ tra cứu so với tra cứu chính mặc dù ông đã chỉ ra YMMV. t.co/MdaktFpbnz Ngoài ra (không phải là vấn đề trong trường hợp này) nhưng bạn phải coi chừng hàng đống nơi bạn thực hiện nhiều thao tác xóa. Bạn có thể tìm thấy chính mình với một rò rỉ không gian. Tôi có một bảng thường xuyên chiếm nhiều GB với 0 hàng.
Kenneth Fisher

-5

FILLFACTOR trên bảng là 100, do đó không có trang miễn phí trong chỉ mục cụm. Nếu bạn đang thực hiện nhiều thao tác chèn, hãy thử đặt FILLFACTOR thành thứ gì đó như 80. Và đọc sách SQL Server trực tuyến về FILLFACTOR. ;-)


2
Đối với trường hợp sử dụng được mô tả trong câu hỏi về việc chèn vào một khóa ngày càng tăng và không có bản cập nhật nào, điều này sẽ chỉ lãng phí không gian.
Martin Smith

Fillfactor không phải là vấn đề (chỉ chèn trang cuối cùng do khóa nhận dạng), autoshrink là vấn đề
Frederik Vanderhaegen
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.