khóa chính và chỉ mục sql


106

Giả sử tôi có một hàng ID (int) trong cơ sở dữ liệu được đặt làm khóa chính. Nếu tôi truy vấn ID thường xuyên, tôi có cần lập chỉ mục nó không? Hay nó là một khóa chính có nghĩa là nó đã được lập chỉ mục?

Lý do tôi hỏi là vì trong MS SQL Server, tôi có thể tạo chỉ mục trên ID này, như tôi đã nêu là khóa chính của tôi.

Chỉnh sửa: một câu hỏi bổ sung - việc lập chỉ mục thêm khóa chính có gây hại gì không?

Câu trả lời:


73

Bạn nói đúng, thật khó hiểu khi SQL Server cho phép bạn tạo các chỉ mục trùng lặp trên (các) trường giống nhau. Nhưng thực tế là bạn có thể tạo một cái khác không cho thấy rằng chỉ số PK cũng không tồn tại.

Chỉ mục bổ sung không tốt, nhưng tác hại duy nhất (rất nhỏ) là kích thước tệp bổ sung và chi phí tạo hàng.


39
Thiệt hại của các chỉ mục không sử dụng thực sự rất có hại. Đối với một điều, các chỉ mục tiêu tốn dung lượng lưu trữ. Đối với một điều khác, nó làm chậm quá trình ghi và cập nhật. Luôn xóa các chỉ mục sẽ không được sử dụng.
Pacerier

50

Như mọi người đã nói, các khóa chính được lập chỉ mục tự động.

Việc tạo thêm chỉ mục trên cột khóa chính chỉ có ý nghĩa khi bạn cần tối ưu hóa truy vấn sử dụng khóa chính và một số cột cụ thể khác. Bằng cách tạo một chỉ mục khác trên cột khóa chính và bao gồm một số cột khác với nó, bạn có thể đạt được sự tối ưu hóa mong muốn cho một truy vấn.

Ví dụ, bạn có một bảng với nhiều cột nhưng bạn chỉ truy vấn các cột ID, Tên và Địa chỉ. Lấy ID làm khóa chính, chúng ta có thể tạo chỉ mục sau được xây dựng dựa trên ID nhưng bao gồm các cột Tên và Địa chỉ.

CREATE NONCLUSTERED INDEX MyIndex
ON MyTable(ID)
INCLUDE (Name, Address)

Vì vậy, khi bạn sử dụng truy vấn này:

SELECT ID, Name, Address FROM MyTable WHERE ID > 1000

SQL Server sẽ chỉ cung cấp cho bạn kết quả bằng cách sử dụng chỉ mục bạn đã tạo và nó sẽ không đọc bất kỳ thứ gì từ bảng thực tế.


28

Chú ý: Đây địa chỉ câu trả lời phát triển doanh nghiệp-lớp in-the-lớn .

Đây là một vấn đề RDBMS, không chỉ SQL Server và hành vi có thể rất thú vị. Đối với một, mặc dù thông thường các khóa chính được lập chỉ mục tự động (duy nhất), nhưng nó KHÔNG phải là tuyệt đối. Đôi khi, điều cần thiết là khóa chính KHÔNG được lập chỉ mục duy nhất.

Trong hầu hết các RDBMS, một chỉ mục duy nhất sẽ tự động được tạo trên một khóa chính nếu một chỉ mục chưa tồn tại . Do đó, bạn có thể tạo chỉ mục của riêng mình trên cột khóa chính trước khi khai báo nó là khóa chính, sau đó chỉ mục đó sẽ được bộ máy cơ sở dữ liệu sử dụng (nếu chấp nhận được) khi bạn áp dụng khai báo khóa chính. Thông thường, bạn có thể tạo khóa chính và cho phép tạo chỉ mục duy nhất mặc định của nó, sau đó tạo chỉ mục thay thế của riêng bạn trên cột đó, sau đó bỏ chỉ mục mặc định.

Bây giờ cho phần thú vị - khi nào bạn KHÔNG muốn một chỉ mục khóa chính duy nhất? Bạn không muốn một cái và không thể dung thứ một cái, khi bảng của bạn có đủ dữ liệu (hàng) để khiến việc duy trì chỉ mục quá tốn kém. Điều này thay đổi dựa trên phần cứng, công cụ RDBMS, đặc điểm của bảng và cơ sở dữ liệu cũng như tải hệ thống. Tuy nhiên, nó thường bắt đầu hiển thị sau khi một bảng đạt đến vài triệu hàng.

Vấn đề thiết yếu là mỗi lần chèn một hàng hoặc cập nhật cột khóa chính dẫn đến việc quét chỉ mục để đảm bảo tính duy nhất. Việc quét chỉ mục duy nhất đó (hoặc tương đương của nó trong bất kỳ RDBMS nào) trở nên đắt hơn nhiều khi bảng phát triển, cho đến khi nó chiếm ưu thế về hiệu suất của bảng.

Tôi đã xử lý vấn đề này nhiều lần với các bảng lớn tới hai tỷ hàng, 8 TB dung lượng lưu trữ và bốn mươi triệu lần chèn hàng mỗi ngày. Tôi được giao nhiệm vụ thiết kế lại hệ thống liên quan, bao gồm việc loại bỏ chỉ mục khóa chính duy nhất thực tế như bước một. Thật vậy, việc giảm chỉ số đó là cần thiết trong sản xuất chỉ đơn giản là để phục hồi sau sự cố ngừng hoạt động, trước khi chúng tôi tiến gần đến việc thiết kế lại. Việc thiết kế lại đó bao gồm việc tìm ra các cách khác để đảm bảo tính duy nhất của khóa chính và cung cấp quyền truy cập nhanh vào dữ liệu.


Điều gì sẽ xảy ra nếu khóa là khóa tự động tăng thêm int hoặc bigint? SQL Server có đủ thông minh để không thực hiện quét chỉ mục duy nhất trong trường hợp này không?
quillbreaker

1
@quillbreaker: một IDENTITYtrường không được đảm bảo là duy nhất. Rốt cuộc, người dùng có thể chèn các giá trị trùng lặp nếu họ sử dụng IDENTITY_INSERT.

Tôi biết đây là một chủ đề cổ xưa, nhưng tôi không hiểu làm thế nào mà việc quét tính duy nhất của một chỉ mục lại gây ra tải trọng như vậy cho hệ thống. Một lần quét B + cây phải là O (log n) * v trong đó v bị hạn chế chi phí đối với phân mảnh chỉ mục, số dư cây không hoàn hảo, v.v. Vì vậy, 2 tỷ hàng sẽ là cơ sở nhật ký 2 của 2.000.000.000 (khoảng 31 tìm kiếm) lần, chẳng hạn như, 2 hoặc 3 hoặc thậm chí 10. 40 triệu lần chèn mỗi ngày là khoảng 462 / giây, ~ 100 IO trên mỗi lần chèn ... Ahh ... Oh. Tôi hiểu rồi. Và đây là trước khi SSD phổ biến.
Charles Burns

Trừ khi bạn bỏ ràng buộc về tính duy nhất, không phải chi phí kiểm tra từng hàng để tìm tính duy nhất sẽ lớn hơn nhiều sao?
Max Candocia

20

Các khóa chính luôn được lập chỉ mục theo mặc định.

Bạn có thể xác định khóa chính trong SQL Server 2012 bằng cách sử dụng SQL Server Management Studio hoặc Transact-SQL. Việc tạo khóa chính sẽ tự động tạo ra một chỉ mục duy nhất, nhóm hoặc không gộp tương ứng.

http://technet.microsoft.com/en-us/library/ms189039.aspx


9

Đây là đoạn trích từ MSDN :

Khi bạn chỉ định ràng buộc KHÓA CHÍNH cho một bảng, Công cụ Cơ sở dữ liệu thực thi tính duy nhất của dữ liệu bằng cách tạo một chỉ mục duy nhất cho các cột khóa chính. Chỉ mục này cũng cho phép truy cập nhanh vào dữ liệu khi khóa chính được sử dụng trong các truy vấn. Do đó, các khóa chính được chọn phải tuân theo các quy tắc tạo chỉ mục duy nhất.


8

một PK sẽ trở thành một chỉ mục được phân nhóm trừ khi bạn chỉ định không được phân nhóm


3

Khai báo một PRIMARY KEYhoặc UNIQUEràng buộc khiến SQL Server tự động tạo chỉ mục.

Một chỉ mục duy nhất có thể được tạo ra mà không cần khớp với một ràng buộc, nhưng một ràng buộc (khóa chính hoặc duy nhất) không thể tồn tại nếu không có một chỉ mục duy nhất.

Từ đây, việc tạo ra một ràng buộc sẽ:

  • khiến một chỉ mục có cùng tên được tạo
  • từ chối bỏ chỉ mục đã tạo vì ràng buộc không được phép tồn tại nếu không có nó

đồng thời bỏ ràng buộc sẽ giảm chỉ mục liên quan.

Vì vậy, có sự khác biệt thực tế giữa a PRIMARY KEYhoặc UNIQUE INDEX:

  • NULLgiá trị không được phép trong PRIMARY KEY, nhưng được phép trong UNIQUEchỉ mục; và giống như trong các toán tử tập hợp (UNION, EXCEPT, INTERSECT), ở đây NULL = NULLcó nghĩa là bạn chỉ có thể có một giá trị vì hai NULLs được tìm thấy là bản sao của nhau;
  • chỉ một chỉ mục PRIMARY KEYcó thể tồn tại trên mỗi bảng trong khi 999 chỉ mục duy nhất có thể được tạo
  • khi PRIMARY KEYràng buộc được tạo, nó được tạo dưới dạng nhóm trừ khi đã có một chỉ mục được nhóm trên bảng hoặc NONCLUSTEREDđược sử dụng trong định nghĩa của nó; khi UNIQUEchỉ mục được tạo, nó được tạo NONCLUSTEREDtrừ khi nó không phải là cụ thể CLUSTEREDvà nó đã không tồn tại;

2

Đặt nó thành khóa chính cũng sẽ tự động tạo chỉ mục cho nó.


1

Nói chung, trong SQL Server, khóa chính được lập chỉ mục tự động. Điều này đúng, nhưng nó không đảm bảo truy vấn nhanh hơn. Khóa chính sẽ mang lại cho bạn hiệu suất tuyệt vời khi chỉ có 1 trường làm khóa chính. Tuy nhiên, khi có nhiều trường làm khóa chính, thì chỉ mục sẽ dựa trên các trường đó.

Ví dụ: Trường A, B, C là khóa chính, do đó, khi bạn thực hiện truy vấn dựa trên 3 trường đó trong WHERE CLAUSE, hiệu suất tốt, NHƯNG khi bạn muốn truy vấn với trường Only C trong WHERE CLAUSE, bạn sẽ không đạt được hiệu suất tốt. Do đó, để bắt đầu và chạy hiệu suất, bạn sẽ cần lập chỉ mục trường C theo cách thủ công.

Hầu hết thời gian, bạn sẽ không thấy vấn đề cho đến khi bạn đạt hơn 1 triệu bản ghi.


0

Tôi có một cơ sở dữ liệu khổng lồ không có chỉ mục (riêng biệt).

Bất kỳ lúc nào tôi truy vấn bằng khóa chính, kết quả sẽ ngay lập tức cho tất cả các mục đích chuyên sâu.


Đó là bởi vì PK là một chỉ mục được phân cụm, hãy xem kế hoạch truy vấn của bạn
SQLMenace

0

khóa chính được lập chỉ mục tự động

bạn có thể tạo chỉ số bổ sung bằng pk tùy thuộc vào cách sử dụng của bạn

  • index zip_code, id có thể hữu ích nếu bạn thường chọn theo zip_code và id
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.