Các chỉ mục được phân nhóm có phải là duy nhất không?


83

Điều gì xảy ra nếu một chỉ mục được phân nhóm không phải là duy nhất? Nó có thể dẫn đến hiệu suất kém vì các dòng được chèn chảy đến một số loại trang "tràn" không?

Nó có được "tạo ra" là duy nhất không và nếu có thì làm thế nào? Cách tốt nhất để làm cho nó trở nên độc đáo là gì?

Tôi đang hỏi bởi vì tôi hiện đang sử dụng chỉ mục được phân nhóm để chia bảng của mình thành các phần hợp lý, nhưng hiệu suất là như vậy và gần đây tôi đã nhận được lời khuyên là hãy làm cho các chỉ mục được phân nhóm của mình là duy nhất. Tôi muốn có ý kiến ​​thứ hai về điều đó.

Cảm ơn!

Câu trả lời:


90

Họ không cần phải là duy nhất nhưng nó chắc chắn được khuyến khích.
Tôi chưa gặp trường hợp nào mà tôi muốn tạo CI trên một cột không phải là duy nhất.

Điều gì xảy ra nếu bạn tạo CI trên một cột không phải là duy nhất

Nếu chỉ mục được phân nhóm không phải là chỉ mục duy nhất, SQL Server tạo bất kỳ khóa trùng lặp nào là duy nhất bằng cách thêm một giá trị được tạo nội bộ được gọi là mã duy nhất

Điều này có dẫn đến hiệu suất xấu không?

Việc thêm một mã duy nhất chắc chắn sẽ làm tăng thêm một số chi phí trong việc tính toán và lưu trữ nó.
Nếu chi phí này sẽ đáng chú ý phụ thuộc vào một số yếu tố.

  • Bảng chứa bao nhiêu dữ liệu.
  • Tỷ lệ chèn là bao nhiêu.
  • Mức độ thường xuyên của CI được sử dụng trong một lựa chọn (khi không có chỉ mục bao hàm nào tồn tại, hầu như luôn luôn).

Chỉnh sửa
như đã được Remus chỉ ra trong phần bình luận, có những trường hợp sử dụng mà việc tạo một CI không phải là duy nhất sẽ là một lựa chọn hợp lý. Tôi không gặp phải một tình huống nào trong số những tình huống đó chỉ đơn thuần cho thấy sự thiếu khả năng tiếp xúc hoặc năng lực của tôi (hãy chọn lựa của bạn).


30
+1 vì mọi thứ bạn nói đều đúng, nhưng chỉ muốn thêm: CI không phải là duy nhất khá phổ biến khi quét phạm vi trên cột cụ thể (không phải duy nhất) là kiểu truy cập phổ biến.
Remus Rusanu

@Remus Rusanu: Tôi đã nghĩ về việc thêm tuyên bố từ chối trách nhiệm vào tuyên bố kịch bản của mình như thế nhưng điều đó không có nghĩa gì cả . Cảm ơn bạn đã chỉ ra một kịch bản mà nó có thể hữu ích.
Lieven Keersmaekers

4
@Remus: vậy ý ​​bạn là tình huống thích hợp khi bạn có một cột không phải là duy nhất như 'Departmentid', nơi bạn truy vấn một cái gì đó như 'DepartmentId GIỮA 1 và 100'? chỉnh sửa ah, tôi hiểu ý bạn, có cột ngày tháng trong bảng ghi nhật ký cũng là một ví dụ điển hình.
littlegreen

Này, tôi có một bảng dòng sự kiện trong đó nhiều hàng tồn tại với cùng một "AggregateId" là một cột cho loại GUID. Các truy vấn duy nhất được thực hiện trên bảng là lấy tất cả các sự kiện cho một AggregateId nhất định. Tôi tự hỏi đây là chỉ mục được phân cụm hay chỉ mục không được phân cụm?
Shayan C

@ShayanC - Nếu hiệu suất truy xuất là mục tiêu chính của bạn, tôi sẽ đặt nó thành CI để có thể lưu trên IO khi truy xuất tất cả các hàng cho một ID nhất định. Như với tất cả các kịch bản hiệu suất, cách chắc chắn duy nhất là đo lường.
Lieven Keersmaekers

32

Tôi muốn xem Nữ hoàng lập chỉ mục, Kimberly Tripp, đã nói gì về chủ đề này:

Tôi sẽ bắt đầu với đề xuất của tôi cho Khóa phân cụm - vì một vài lý do. Thứ nhất, đó là một quyết định dễ thực hiện và thứ hai, đưa ra quyết định này sớm giúp chủ động ngăn chặn một số loại phân mảnh. Nếu bạn có thể ngăn chặn một số kiểu phân mảnh bảng cơ sở thì bạn có thể giảm thiểu một số hoạt động bảo trì (một số trong số đó, trong SQL Server 2000 VÀ ít hơn trong SQL Server 2005) yêu cầu bảng của bạn phải ngoại tuyến. Được rồi, tôi sẽ quay lại phần xây dựng lại sau .....

Hãy bắt đầu với những điều quan trọng mà tôi tìm kiếm trong một khóa phân cụm:

* Unique
* Narrow
* Static

Tại sao duy nhất? Khóa phân cụm phải là duy nhất vì khóa phân cụm (khi một khóa tồn tại) được sử dụng làm khóa tra cứu từ tất cả các chỉ mục không phân cụm. Lấy ví dụ một chỉ mục ở phía sau sách - nếu bạn cần tìm dữ liệu mà mục nhập chỉ mục trỏ đến - mục nhập đó (mục nhập chỉ mục) phải là duy nhất, nếu không thì mục nhập chỉ mục nào sẽ là mục bạn đang tìm ? Vì vậy, khi bạn tạo chỉ mục nhóm - nó phải là duy nhất. Tuy nhiên, SQL Server không yêu cầu khóa phân cụm của bạn được tạo trên một cột duy nhất. Bạn có thể tạo nó trên bất kỳ (các) cột nào bạn muốn. Trong nội bộ, nếu khóa phân cụm không phải là duy nhất thì SQL Server sẽ "hợp nhất" nó bằng cách thêm một số nguyên 4 byte vào dữ liệu. Vì vậy, nếu chỉ mục nhóm được tạo trên một cái gì đó không phải là duy nhất thì không chỉ có thêm chi phí khi tạo chỉ mục mà còn có không gian đĩa bị lãng phí,

Nguồn: Cuộc tranh luận chính theo cụm ngày càng gia tăng - một lần nữa!


Tuy nhiên, một câu hỏi được đặt ra, Queen đề xuất một newsequentialid để thống nhất dữ liệu, nhưng SQL Server tạo ra uniquifier của riêng nó nếu bạn không chỉ định nó. Sau đó, vẫn còn bất kỳ lý do nào để thêm id tuần tự của riêng bạn?
littlegreen

2
@littlegreen: cô ấy nói nếu bạn khăng khăng sử dụng GUID (thực sự không tốt khi sử dụng trong chỉ mục phân cụm), thì ít nhất hãy sử dụng newsequentialid()để có được GUID gần như tuần tự. Nhưng có: nếu bạn thêm ID duy nhất của riêng mình (tôi luôn thích INT IDENTITY hơn), thì bạn có giá trị đó trong tay và bạn có thể sử dụng nó (ví dụ: để thiết lập mối quan hệ FK). Các mã duy nhất được thêm vào của SQL Server sẽ ẩn đối với bạn và do đó chúng chỉ là chi phí mà bạn không thể sử dụng.
marc_s

Tôi hiểu rồi. Chà, đó sẽ là một lập luận ủng hộ một chỉ mục nhóm (ID CompanyID, DepartmentID, id INT IDENTITY) thay vì chỉ hai chỉ mục đầu tiên. Cảm ơn!
littlegreen

1
@littlegreen: tốt hơn - làm cho nhóm chỉ số của bạn chỉ trên (ID INT IDENTITY) và đưa các lĩnh vực khác - nếu cần - vào một tổ chức phi-clustered index, riêng biệt. Chỉ mục được phân nhóm phải càng nhỏ càng tốt - sau cùng, các cột chỉ mục được phân nhóm đang được thêm vào từng mục nhập của từng và mọi chỉ mục không được phân nhóm trên bảng đó - vì vậy đừng lãng phí các byte của bạn với một nhóm rộng mục lục!
marc_s

1
Có nhưng sau đó tôi mất lợi ích khi tất cả dữ liệu bộ phận của tôi được nhóm lại và tôi có thể chèn / xóa / truy xuất toàn bộ bộ phận cùng một lúc. Dữ liệu của tôi sẽ bị phân tán và việc chèn / xóa trên toàn bộ bộ phận hoặc thậm chí toàn bộ công ty sẽ bị chậm. Các truy vấn của tôi chỉ chạy trên một công ty cùng một lúc và thường thì toàn bộ tập dữ liệu cần được cập nhật.
littlegreen

9

Các chỉ mục được phân nhóm có phải là duy nhất không?

Họ không làm như vậy, và có những lúc sẽ tốt hơn nếu không.

Hãy xem xét một bảng với một EmployeeId bán ngẫu nhiên, duy nhất và một DepartmentId cho mỗi nhân viên: nếu câu lệnh lựa chọn của bạn là

SELECT * FROM EmployeeTable WHERE DepartmentId=%DepartmentValue%

thì tốt nhất cho hiệu suất nếu đây DepartmentIdlà chỉ mục được phân cụm mặc dù (hoặc thậm chí đặc biệt là vì) nó không phải là chỉ mục duy nhất (tốt nhất cho hiệu suất vì nó đảm bảo rằng tất cả các bản ghi trong một DepartmentId nhất định được nhóm lại).


Bạn có lời khuyên nào chưa?

Clustered Index Hướng dẫn thiết kế ví dụ mà nói,

Với một vài ngoại lệ, mọi bảng phải có một chỉ mục được phân nhóm được xác định trên cột hoặc các cột, cung cấp những điều sau:

  • Có thể được sử dụng cho các truy vấn thường xuyên sử dụng.
  • Cung cấp một mức độ độc đáo cao.
  • Có thể được sử dụng trong các truy vấn phạm vi.

Ví dụ, hiểu biết của tôi về "mức độ độc đáo cao" là không tốt nếu chọn "Quốc gia" làm chỉ mục kết hợp nếu hầu hết các truy vấn của bạn muốn chọn các bản ghi trong một thị trấn nhất định.


Vâng, đó là những gì tôi nghĩ cho đến bây giờ, nhưng tôi cũng nhận được lời khuyên hoàn toàn ngược lại, vì vậy tôi tự hỏi đâu là sự thật. Bạn có lời khuyên nào chưa?
littlegreen

@littlegreen Tôi đã chỉnh sửa câu trả lời của mình để cố gắng trả lời câu hỏi của bạn.
ChrisW

Cảm ơn. Được rồi, tôi hiểu ý của bạn. Nhưng nếu bạn thường xuyên chèn cả một quốc gia cùng một lúc, một chỉ mục nhóm trên (quốc gia, thị trấn) sẽ có vẻ cồng kềnh với tôi vì nó yêu cầu phân loại dữ liệu. Mặt khác, một loại trước khi chèn sẽ không được rằng có rất nhiều rắc rối ...
littlegreen

3
Chắc chắn trong ví dụ của bạn, chỉ mục nhóm duy nhất trên {DepartmentID, EmployeeID} sẽ thích hợp hơn? Tại sao hệ thống lại tạo mã duy nhất khi trường hiện tại của bạn sẽ cung cấp tính duy nhất với chi phí thấp hơn (có thể là INT bốn byte) và có thể cho phép bạn chạy thêm một vài truy vấn trong chỉ mục?
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.