Chỉ mục trên một cột danh tính không nên được bao gồm?


19

Đối với một bảng có cột định danh, nên tạo một chỉ mục PK / duy nhất được phân cụm hoặc không phân cụm cho cột định danh?

Lý do là các chỉ mục khác sẽ được tạo cho các truy vấn. Một truy vấn sử dụng một chỉ mục không bao gồm (trên một heap) và trả về các cột không được bao phủ bởi chỉ mục sẽ sử dụng I / O (LIO) ít logic hơn vì không có các bước tìm kiếm b-cây chỉ mục được thêm cụm?

create table T (
  Id int identity(1,1) primary key, -- clustered or non-clustered? (surrogate key, may be used to join another table)
  A .... -- A, B, C have mixed data type of int, date, varchar, float, money, ....
  B ....
  C ....
  ....)

create index ix_A on T (A)
create index ix_..... -- Many indexes can be created for queries

-- Common query is query on A, B, C, ....
select A, B 
from T 
where A between @a and @a+5 -- This query will have less LIO if the PK is non-clustered (seek)

select A, B, C
from T 
where B between @a and @a+5 

....

PK cụm trên cột nhận dạng là tốt bởi vì:

  1. Nó tăng đơn điệu để không chia trang khi chèn. Người ta nói rằng một số lượng lớn có thể nhanh như trên một bảng (không bao gồm)

  2. Nó hẹp

Tuy nhiên, các truy vấn trong câu hỏi sẽ nhanh hơn mà không cần đặt cụm?

** Cập nhật: ** Điều gì xảy ra nếu IdFK của các bảng khác và nó sẽ được tham gia trong một số truy vấn?


3
Nó không tốt hơn hay tệ hơn, nó phụ thuộc.
Aaron Bertrand

1
@ypercube Liên kết kejser.org/clustered-indexes-vs-heaps nói rằng người không CI sẽ có ít LIO hơn.
u23432534

2
Tôi đã đọc bài viết trong quá khứ và nó chắc chắn chỉ ra rằng có những trường hợp cho một chỉ mục cụm và trường hợp cho một đống. Nó không phải là tất cả màu đen hoặc trắng.
ypercubeᵀᴹ

4
Tôi không chắc rằng phản hồi của bạn với @ypercube đáp ứng bất kỳ tiêu chí nào được trích dẫn bởi ông Kejser - ít nhất là với các chi tiết bạn đã chia sẻ. Ở dạng hiện tại, tôi thực sự không chắc chắn rằng điều này sẽ tạo ra một câu trả lời hữu ích bởi vì nó sẽ phải bao gồm gần như mọi kịch bản duy nhất - đã được thực hiện trong bài đăng trên blog mà bạn đã trích dẫn. Nếu bạn có thể cung cấp thêm chi tiết về kịch bản cụ thể của mình thì có thể một số kiến ​​thức trong bài có thể được áp dụng.
swasheck

2
Nó sẽ phụ thuộc vào những thứ như: a) khối lượng công việc (OLTP? OLAP? Vv?), B) kích thước bảng (s), c) dạng bình thường, chỉ để đặt tên cho một số. Bạn đã không cung cấp chi tiết về bất kỳ yếu tố nào trong số này, vì vậy mọi khuyến nghị sẽ dựa trên dự đoán từ môi trường của bạn. Ngoài ra, bạn đã thử cấu hình các truy vấn mà bạn đang đề xuất (với bộ đệm đã xóa) và nhận các cấu hình IO cụ thể cho mỗi cấu hình và tự mình xem chưa?
swasheck

Câu trả lời:


16

Theo mặc định, PK được phân cụm và trong hầu hết các trường hợp, điều này là tốt. Tuy nhiên, câu hỏi nào nên được hỏi:

  • PK của tôi có nên được nhóm lại không?
  • cột nào sẽ là khóa tốt nhất cho chỉ mục được nhóm của tôi?

Chỉ số PK và Clustered là 2 điều khác biệt:

  • PK là một hạn chế. PK được sử dụng để xác định các hàng duy nhất, nhưng không có khái niệm về lưu trữ. Tuy nhiên, theo mặc định (trong SSMS), nó được thi hành bởi một chỉ mục cụm duy nhất nếu chưa có chỉ mục cụm.
  • Các chỉ mục được nhóm là một loại chỉ mục đặc biệt lưu trữ dữ liệu hàng ở cấp độ lá, có nghĩa là nó luôn luôn bao phủ. Tất cả các cột cho dù chúng là một phần của khóa hay không, được lưu trữ ở cấp độ lá. Nó không phải là duy nhất, trong trường hợp đó, một bộ duy nhất (4 byte) được thêm vào khóa cụm.

Bây giờ chúng tôi kết thúc với 2 câu hỏi:

  • Làm cách nào để tôi xác định duy nhất các hàng trong bảng của mình (PK)
  • Làm thế nào để tôi muốn lưu trữ nó ở cấp độ lá của một chỉ mục (Chỉ mục cụm)

Nó phụ thuộc vào cách:

  • bạn thiết kế mô hình dữ liệu của bạn
  • bạn truy vấn dữ liệu của bạn và bạn viết truy vấn của bạn
  • bạn chèn hoặc cập nhật dữ liệu của bạn
  • ...

Đầu tiên, bạn có cần một chỉ số cụm? Nếu bạn chèn số lượng lớn, sẽ hiệu quả hơn khi lưu trữ dữ liệu không có thứ tự vào HEAP (so với dữ liệu được sắp xếp trong một cụm). Nó sử dụng RID (Định danh hàng, 8 byte) để xác định duy nhất các hàng và lưu trữ nó trên các trang.

Chỉ số cụm không nên là một giá trị ngẫu nhiên. Dữ liệu ở cấp độ lá sẽ được lưu trữ và sắp xếp theo khóa chỉ mục. Do đó, nó nên phát triển liên tục để tránh phân mảnh hoặc chia trang. Nếu PK không thể đạt được điều này, bạn nên xem xét một khóa khác như một ứng cử viên. Chỉ mục được nhóm trên các cột nhận dạng, GUID tuần tự hoặc thậm chí một cái gì đó như ngày chèn là tốt từ quan điểm tuần tự vì tất cả các hàng sẽ được thêm vào trang lá cuối cùng. Mặt khác, mặc dù số nhận dạng duy nhất có thể hữu ích cho nhu cầu kinh doanh của bạn dưới dạng PK, nhưng chúng không nên được phân cụm (chúng được sắp xếp / tạo ngẫu nhiên).

Nếu sau khi phân tích một số dữ liệu và truy vấn, bạn phát hiện ra rằng bạn chủ yếu sử dụng cùng một chỉ mục để lấy dữ liệu của mình trước khi thực hiện tra cứu khóa trong PK cụm, bạn có thể coi đó là chỉ mục cụm mặc dù nó có thể không xác định duy nhất dữ liệu của bạn.

Khóa chỉ mục được nhóm bao gồm tất cả các cột bạn muốn lập chỉ mục. Một cột duy nhất (4 byte) được thêm vào nếu không có ràng buộc duy nhất nào trên nó (giá trị gia tăng cho các bản sao, nếu không thì khác). Khóa chỉ mục này sau đó sẽ được lưu trữ một lần cho mỗi hàng ở cấp độ lá của tất cả các chỉ mục không bao gồm của bạn. Một số trong số chúng cũng sẽ được lưu trữ nhiều lần ở các cấp trung gian (nhánh) giữa gốc và cấp lá của cây chỉ mục (cây B). Nếu khóa quá lớn, tất cả các chỉ mục không được phân cụm sẽ trở nên lớn hơn, sẽ cần nhiều bộ nhớ hơn và nhiều IO, CPU, bộ nhớ, ... Nếu bạn có PK về tên + ngày sinh + quốc gia, rất có khả năng khóa này không phải là một ứng cử viên tốt Nó là quá lớn cho một chỉ số cụm. Trình nhận dạng duy nhất sử dụng NEWSEQUENTIALID () thường không được coi là một khóa hẹp (16 byte) mặc dù nó là tuần tự.

Sau đó, khi bạn tìm ra cách xác định duy nhất các hàng trong bảng của mình, bạn có thể thêm PK. Nếu bạn nghĩ rằng bạn sẽ không sử dụng nó trong truy vấn của mình, đừng tạo nó thành cụm. Bạn vẫn có thể tạo một chỉ mục không bao gồm khác nếu đôi khi bạn cần truy vấn nó. Lưu ý rằng PK sẽ tự động tạo ra một chỉ mục duy nhất.

Các chỉ mục không được phân cụm sẽ luôn chứa khóa được phân cụm. Tuy nhiên, nếu các cột được lập chỉ mục (+ cột chính) đang che, sẽ không có bất kỳ tra cứu khóa nào trong chỉ mục được nhóm. Đừng quên bạn cũng có thể thêm Bao gồm và Vị trí vào một chỉ mục không được nhóm. (sử dụng nó một cách rộng rãi)

Chỉ mục cụm nên là duy nhất và càng hẹp càng tốt Chỉ mục cụm không nên thay đổi theo thời gian và nên được chèn tăng dần.

Bây giờ là lúc để viết một số SQL sẽ tạo bảng, các chỉ mục và các ràng buộc không được bao gồm và không được bao gồm.

Đây chỉ là lý thuyết vì chúng tôi không biết mô hình dữ liệu và kiểu dữ liệu của bạn được sử dụng (A và B).


11

Đối với một bảng có khóa chính (PK) trên cột nhận dạng, nó sẽ được phân cụm theo mặc định. Nó có thể tốt hơn như không bao gồm?

Nếu bạn đang hỏi liệu mặc định cho khóa chính trên cột nhận dạng (cụ thể) có nên không bị loại bỏ hay không, tôi sẽ nói không. Hầu hết các bảng đều có lợi từ việc có một chỉ mục được nhóm, do đó, việc tạo cụm mặc định cho ràng buộc khóa chính có thể hữu ích về mặt tổng thể, đặc biệt đối với người dùng mới của SQL Server.

Giống như bất kỳ tùy chọn nào, luôn có những trường hợp khác nhau được ưu tiên so với trường hợp khác, nhưng một DBA có kinh nghiệm nên biết về mặc định và có thể ghi đè lên khi thích hợp. Cũng xem phần Hỏi & Đáp liên quan, Khi nào một khóa chính sẽ được khai báo không được bao gồm? .

Các truy vấn trong câu hỏi sẽ nhanh hơn mà không cần đặt nó cụm?

Có, nhưng hãy cẩn thận.

Tra cứu RID thực sự hiệu quả hơn tra cứu Key. Ngay cả khi tất cả các trang bắt buộc nằm trong bộ nhớ (rất có thể dành cho các cấp trên của một chỉ mục), vẫn có một chi phí CPU liên quan đến việc điều hướng cây b-index của cụm. Kết quả là, SQL Server thường có thể thực hiện nhiều lần tra cứu RID hơn so với tra cứu khóa trên mỗi đơn vị thời gian CPU.

Hãy cẩn thận

Ở trên thường không phải là một yếu tố quyết định khi quyết định có cấu trúc một bảng như một đống hay không. Sẽ là không thực tế để tránh tra cứu (sử dụng chỉ số che phủ) và số lần tra cứu sẽ phải đủ lớn để có tác động (và quan trọng) đến hiệu suất, dựa trên môi trường phần cứng và khối lượng công việc.

Nó không thực sự thiết thực để bao gồm tất cả các khía cạnh của cuộc tranh luận về chỉ số heap vs nhóm trong câu trả lời này, nhưng tôi sẽ nói rằng có khá ít lý do chính đáng để thích cấu trúc một bảng như một đống nói chung. Đối với tôi, việc chọn loại thiết kế được đề xuất trong câu hỏi sẽ đòi hỏi một phân tích rất cẩn thận trước khi thực hiện và sẽ phải đáp ứng một thanh cao. Lập luận chung về 'khả năng mở rộng' sẽ không đủ.

Liên quan đến việc cập nhật câu hỏi về tham gia, việc đánh giá tác động của việc mất chỉ số cụm trên các kế hoạch thực hiện sẽ là một phần của phân tích được đề cập ở trên. Nếu các vòng lặp lồng nhau được sử dụng, sẽ rất thuận tiện khi có chỉ mục được nhóm trên khóa tham gia vì tất cả các cột từ hàng có sẵn ngay lập tức mà không cần tra cứu.

Kinh nghiệm của riêng tôi là việc có các chỉ mục cụm duy nhất trên các cột danh tính rất thường có lợi, tất cả mọi thứ đều được xem xét. Tôi đã tìm thấy rất nhiều vấn đề về quản lý không gian và tôi cũng nên đề cập rằng một số tính năng của SQL Server yêu cầu một chỉ mục cụm duy nhất để hoạt động.


8

Trên thực tế, bạn không cần Chỉ mục cụm cũng như Khóa chính được tạo, vì Chỉ mục duy nhất và Chỉ mục không duy nhất có thể xử lý công việc. SQL Server đã hỗ trợ Chỉ mục cụm từ ít nhất là phiên bản 1.1, nhưng Khóa chính chỉ là một "khái niệm" mà các lập trình viên thực thi bằng cách xác định một chỉ mục duy nhất.

Nhưng dường như cả Khóa chính và Chỉ mục cụm là các khái niệm có giá trị trong phần lớn các cơ sở dữ liệu.

Chúng ta hãy xem tài liệu SQL Server để xem các mô tả một phần của một số tùy chọn lập chỉ mục như hiển thị bên dưới.

Chỉ mục được nhóm: https://msdn.microsoft.com/en-us/l Library / ms190457.aspx

  • Các chỉ mục được nhóm sắp xếp và lưu trữ các hàng dữ liệu trong bảng hoặc dạng xem dựa trên các giá trị chính của chúng. Đây là các cột được bao gồm trong định nghĩa chỉ mục.
  • Chỉ có thể có một chỉ mục được nhóm trên mỗi bảng

Khóa chính: https://msdn.microsoft.com/en-us/l Library / ms190457.aspx

  • Một bảng chỉ có thể chứa một ràng buộc CHÍNH CHÍNH.

  • Tất cả các cột được xác định trong một ràng buộc CHÍNH CHÍNH phải được xác định là KHÔNG NULL.

  • Khóa chính có thể được tạo dưới dạng Chỉ mục cụm (mặc định nếu không có Chỉ mục cụm) hoặc Chỉ mục không cụm.

Chỉ mục duy nhất: https://msdn.microsoft.com/en-us/l Library / ms187019.aspx

  • Khi bạn tạo một ràng buộc UNIITE, một chỉ mục không bao gồm duy nhất được tạo để thực thi một ràng buộc UNIITE theo mặc định.

  • Bạn có thể chỉ định Chỉ mục cụm đơn nhất nếu Chỉ mục cụm chưa tồn tại cho bảng.

Điều này có nghĩa là câu hỏi của bạn về Chỉ mục cụm và Khóa chính thực sự là về một số vấn đề sau. Xin lưu ý rằng không phải mọi bảng đều có lợi từ cùng một kế hoạch lập chỉ mục.

Khi nào tôi sẽ được hưởng lợi từ Khóa chính tách biệt với Chỉ mục cụm?

Có lẽ khi Chỉ mục cụm là rộng (ví dụ: 5 cột thông tin văn bản, nhưng Khóa chính là nhỏ (INT hoặc BIGINT), chẳng hạn như bạn dường như đang mô tả.

  • Chỉ mục cụm rộng sẽ cho phép bạn nhanh chóng chọn các hàng từ chỉ mục cho một tập hợp truy vấn cung cấp câu trả lời nối tiếp từ Chỉ mục cụm (còn được gọi là Bảng ). Ví dụ: Chỉ mục cụm 5 cột sẽ hỗ trợ quét các cột C1, C2, C3, C4, C5 hoặc C1, C2, C3, C4, v.v. xuống C1.
  • Lưu ý: Nếu các hàng lớn, điều này có thể mang lại cho bạn một số lợi ích về tốc độ khi chọn bộ hàng nối tiếp , đặc biệt là nếu các cột khác trong bảng thường xuyên được bao gồm trong tập kết quả.
  • Trong trường hợp đó, bạn có thể sử dụng Khóa chính cho tính toàn vẹn tham chiếu để cung cấp giá trị cần thiết dưới dạng Khóa ngoài để ràng buộc các hàng trong các bảng khác. PK là nhỏ và do đó FK là một điểm nhấn nhỏ trên kích thước của (các) bảng được tham chiếu.
  • Tuy nhiên, lưu ý rằng bất kỳ chỉ mục nào được tạo trên bảng có Chỉ mục cụm sẽ bao gồm tất cả các cột cụm trong các chỉ mục khác bạn tạo trên bảng này. Một chỉ mục cụm rộng sẽ mở rộng kích thước của tất cả các chỉ mục không được nhóm trên bảng đó.

Bạn có nên biến Khóa chính một mình thành Chỉ mục cụm?

  • Nếu bạn có một Khóa chính nhỏ (INT hoặc BIGINT) và đó là Chỉ mục cụm, thì tổng chi phí của các cột cụm tương đối nhỏ. Mặc dù Khóa chính cụm trong trường hợp này cũng sẽ tồn tại trong mọi chỉ mục trên bảng này, nhưng đó là một mức giá nhỏ hơn để trả so với Cụm rộng được thảo luận ở trên.

  • Chỉ mục cụm khóa chính này thường sẽ không trực tiếp cung cấp một đường dẫn dễ dàng để chọn nhiều hàng.

  • Bây giờ bạn đã tạo Khóa chính cụm , vậy còn những cột khác mà bạn đã từng dự định đưa vào Chỉ mục cụm thì sao?

  • Tạo một chỉ mục duy nhất (hoặc không duy nhất) khi cần để lập chỉ mục tiêu chí tìm kiếm rộng đó của các cột C1, C2, C3, C4, C5. Các giá trị trong Chỉ mục Bắt chước cụm sao giả này có thể đóng vai trò là đường dẫn tìm kiếm nhanh hơn cho 5 cột đó. Nếu có một hoặc hai cột không được lập chỉ mục thường xuyên được chọn, chúng có thể được bao gồm trong chỉ mục với INCLUDE (Doctor_Name, Diagnosis_Synopsis).

Mặc dù tôi thấy các Chỉ mục cụm và Khóa chính đơn giản hữu ích, có một số lý do chính đáng để suy nghĩ xem nên sử dụng chúng trong bảng hoặc trong cơ sở dữ liệu.

Bạn có cần một Chỉ số cụm nào không?

  • Nếu bạn tạo các chỉ mục (Chỉ mục duy nhất và Chỉ mục không duy nhất) và xác định Khóa chính mà không phải là Chỉ số cụm, bạn có thể thấy rằng các chỉ mục hẹp hơn cung cấp cho bạn những gì bạn cần cho các truy vấn của mình.

  • Có một số hành vi hữu ích trong Chỉ mục cụm và Khóa chính, nhưng hãy nhớ rằng đó thực sự là chỉ mục quan trọng nhất. Thiết kế chiến lược lập chỉ mục để tính đến thực tế của ứng dụng của bạn. Có lẽ OneBigTablecần phải có một chiến lược lập chỉ mục khác với những gì bạn sử dụng cho hầu hết các bảng.

  • Nếu không có Chỉ mục cụm, dữ liệu của bạn sẽ được lưu trữ dưới dạng một đống với Mã định danh hàng (RID) hoàn toàn không phải là một cơ chế tìm kiếm tốt. Nhưng, như đã đề cập trước đây, bạn có thể tạo các chỉ mục duy nhất và không duy nhất để xử lý các truy vấn của mình.

Bây giờ sẽ đưa bạn xem xét Heaps:

Heaps và Index: https://msdn.microsoft.com/en-us/l Library / hh213609.aspx

  • Khi một bảng được lưu trữ dưới dạng heap, các hàng riêng lẻ được xác định bằng cách tham chiếu đến một mã định danh hàng (RID) bao gồm số tệp, số trang dữ liệu và vị trí trên trang. Id hàng là một cấu trúc nhỏ và hiệu quả. (Nhưng nó không phải là một chỉ mục .)
  • Đô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 bao gồm và RID nhỏ hơn khóa chỉ mục được nhóm .

Nhưng nếu bạn cũng có một số 'điểm nóng' trong một tập dữ liệu lớn, bạn cũng có thể xem xét một loại chỉ mục khác:

Chỉ mục được lọc: https://msdn.microsoft.com/en-us/l Library / cc280372.aspx

  • Một chỉ mục được lọc được thiết kế tốt sẽ cải thiện hiệu năng truy vấn và chất lượng kế hoạch thực hiện vì nó nhỏ hơn chỉ mục không chứa toàn bảng và có các số liệu thống kê được lọc. Thống kê được lọc chính xác hơn thống kê toàn bảng vì chúng chỉ bao gồm các hàng trong chỉ mục được lọc .

  • Các chỉ mục được lọc có một số hạn chế được nêu trong liên kết đến các chỉ mục được lọc.

Tuy nhiên, nếu bạn muốn suy nghĩ về khả năng bỏ qua Khóa chính và Chỉ mục cụm hoàn toàn, bạn có thể đọc bài đăng của Markus Winand được liên kết bên dưới. Ông chứng minh lý do của mình, với một số mẫu mã, để đề xuất rằng đôi khi có thể nên sử dụng các tính năng đó.

http://use-the-index-luke.com/blog/2014-01/unreasonable-defaults-primary-key-clustering-key

Nhưng cuối cùng tất cả quay trở lại để hiểu ứng dụng của bạn và thiết kế mã, bảng, chỉ mục, v.v. để phù hợp với công việc bạn đang làm.


Đối với những gì nó có giá trị, trong công việc hàng ngày của tôi nếu tôi tìm thấy một bảng là một đống, tôi coi đó rất có thể là một lỗi và kiểm tra với các nhà phát triển để xem liệu nó có phải là một đống cố ý hay không.
RLF

-2

Một vài điểm để xem xét.

Mặc dù một chỉ mục (được nhóm hoặc không) trên một giá trị tăng đơn điệu giúp bạn chia tách trang trong khi chèn hàng loạt, nó tạo ra một điểm nóng mới ở phần đuôi của chỉ mục. Mặc dù nó có thể không phải là vấn đề với một chuỗi chèn đơn luồng, nhưng nó chắc chắn sẽ tăng sự tranh chấp cho một ứng dụng đa luồng chèn các bộ dữ liệu mới với tốc độ cao, vì các luồng sẽ liên tục cạnh tranh để truy cập vào trang cuối cùng của chỉ mục.

Phân cụm bảng dựa trên PK thay thế (danh tính) hiếm khi có lợi. Một khóa chính như vậy chủ yếu được sử dụng để truy cập các bộ dữ liệu riêng lẻ, từng bộ một hoặc quét toàn bộ chỉ mục để tham gia. Trong cả hai trường hợp, không quan trọng là chỉ mục có được nhóm hay không (ngoại trừ các phép nối hợp nhất, có thể, nhưng chúng có thường xuyên không?)

Tôi nghĩ rằng bạn sẽ được hưởng lợi nhiều nhất từ ​​một chỉ mục được nhóm bao gồm các truy vấn yêu cầu quét phạm vi chính và các vị từ bổ sung tham chiếu các cột khác.


Làm thế nào cao tỷ lệ phải có để điều này thực sự trở thành một vấn đề?
ypercubeᵀᴹ

@ypercube tôi có thể nói "nó phụ thuộc" không? Bởi vì nó làm. Trong trường hợp không có trình kích hoạt trên bàn, tôi hy vọng sẽ bắt đầu trải qua một số cuộc tranh cãi với hàng tá chủ đề với tổng số 1K chèn mỗi giây.
mustaccio


Tôi không đồng ý nhưng tôi đã hỏi người ta có thể đi bao xa với một điểm nóng. Tôi nhớ đã thấy một bài viết về việc chèn 30K hàng mỗi giây trong một bảng có IDENTITY là CI (nếu bộ nhớ phục vụ tốt cho tôi) nhưng tôi không thể tìm thấy bài đăng trên blog.
ypercubeᵀᴹ

Thảo luận này là vô nghĩa trong trường hợp không có khối lượng công việc cụ thể chạy với lược đồ cụ thể trên phần cứng cụ thể. Tôi hy vọng tất cả chúng ta có thể đồng ý rằng một chỉ số trên chuỗi tăng đơn điệu sẽ tạo ra một "điểm nóng"; nó sẽ tạo ra một nút cổ chai không thể chấp nhận được và liệu người ta có nên quan tâm đến nó hay không phụ thuộc vào hoàn cảnh.
mustaccio
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.