SQL - khóa chính của nhiều bảng


125

Câu hỏi này xuất hiện sau khi đọc một bình luận trong câu hỏi này:

Thiết kế cơ sở dữ liệu

Khi bạn tạo một bảng nhiều đến nhiều, bạn nên tạo khóa chính tổng hợp trên hai cột khóa ngoại hoặc tạo khóa chính "ID" thay thế tự động tăng dần và chỉ đặt chỉ mục trên hai cột FK của bạn (và có thể một ràng buộc duy nhất)? Những tác động đến hiệu suất chèn bản ghi mới / lập chỉ mục lại trong mỗi trường hợp là gì?

Về cơ bản, điều này:

PartDevice
----------
PartID (PK/FK)
DeviceID (PK/FK)

so với cái này:

PartDevice
----------
ID (PK/auto-increment)
PartID (FK)
DeviceID (FK)

Người bình luận nói:

làm cho hai ID trở thành PK có nghĩa là bảng được sắp xếp vật lý trên đĩa theo thứ tự đó. Vì vậy, nếu chúng ta chèn (Part1 / Device1), (Part1 / Device2), (Part2 / Device3), thì (Part 1 / Device3) cơ sở dữ liệu sẽ phải tách bảng ra và chèn cái cuối cùng vào giữa mục 2 và 3. Đối với nhiều bản ghi, điều này trở nên rất khó khăn vì nó liên quan đến việc xáo trộn hàng trăm, hàng nghìn hoặc hàng triệu bản ghi mỗi khi một bản ghi được thêm vào. Ngược lại, PK tự động gia tăng cho phép các bản ghi mới được gắn vào cuối cùng.

Lý do tôi hỏi là vì tôi luôn có xu hướng làm khóa chính tổng hợp mà không có cột tăng tự động thay thế, nhưng tôi không chắc liệu khóa thay thế có thực sự hiệu quả hơn không.


Đây là một câu hỏi silimar được đăng trên SO: stackoverflow.com/questions/344068/…
Tony

(Đã cố gắng thêm điều này vào nhận xét trước đây của tôi nhưng không thể) Tùy thuộc vào số lượng chèn, bạn cũng có thể định kỳ xây dựng lại chỉ mục của mình để đảm bảo nó trả về kết quả nhanh chóng. Trong SQL Server, bạn cũng có thể tinh chỉnh FILLFACTOR của chỉ mục để cung cấp đủ không gian cho các lần chèn trước khi nó phải di chuyển dữ liệu.
Tony

1
Câu trả lời cho điều này không phụ thuộc vào những gì DBMS được sử dụng? Tôi nghi ngờ MySQL sẽ hoạt động theo một cách nào đó trong trường hợp này, SQL-Server hơi theo một cách khác, v.v.
Radu Murzea

Lưu ý: Không có thẻ cơ sở dữ liệu cụ thể, phần lớn những gì được nói ở đây là đáng ngờ. Các động cơ khác nhau hoạt động khác nhau!
Rick James

Câu trả lời:


85

Với một ánh xạ nhiều-nhiều hai cột đơn giản, tôi không thấy lợi ích thực sự nào khi có một khóa thay thế. Việc bật khóa chính (col1,col2)được đảm bảo là duy nhất (giả sử giá trị của bạn col1col2các giá trị trong bảng được tham chiếu là duy nhất) và một chỉ mục riêng trên (col2,col1)sẽ bắt được những trường hợp mà lệnh ngược lại sẽ thực thi nhanh hơn. Người thay thế là một sự lãng phí không gian.

Bạn sẽ không cần chỉ mục trên các cột riêng lẻ vì bảng chỉ nên được sử dụng để nối hai bảng được tham chiếu lại với nhau.

Theo ý kiến ​​của tôi, nhận xét mà bạn đề cập đến trong câu hỏi không đáng giá bằng các electron mà nó sử dụng. Nghe có vẻ như tác giả nghĩ rằng bảng được lưu trữ trong một mảng chứ không phải là một cấu trúc cây đa chiều cân bằng hiệu suất cực cao.

Để bắt đầu, không bao giờ cần thiết phải lưu trữ hoặc lấy tại bảng được sắp xếp, chỉ cần chỉ mục. Và chỉ mục sẽ không được lưu trữ tuần tự, nó sẽ được lưu trữ theo cách hiệu quả để có thể được truy xuất nhanh chóng.

Bên cạnh đó, đại đa số các bảng cơ sở dữ liệu được đọc xa hơn thường xuyên hơn bằng văn bản. Điều đó làm cho bất kỳ điều gì bạn làm ở phía được chọn có liên quan hơn nhiều so với bất kỳ thứ gì ở phía chèn.


Điểm cuối cùng không phải là một khái quát tốt: "phần lớn các bảng cơ sở dữ liệu được đọc thường xuyên hơn nhiều so với được viết". Tôi tìm thấy nhiều ví dụ về các bảng liên kết cần được ghi vào rất thường xuyên, ví dụ như bảng liên kết khách hàng đặt hàng.
người dùng

5
@buffer, tôi sẽ đứng về phía nhận xét đó (về mặt kỹ thuật, nó chỉ là khái quát nếu tôi nói "tất cả các bảng", "đại đa số" là dựa trên kinh nghiệm). Hãy cũng suy nghĩ về ví dụ của bạn, một đơn đặt hàng được tạo một lần (thỉnh thoảng nó có thể được cập nhật nhưng điều đó không có khả năng thay đổi thông tin khóa / chỉ mục, nhiều hơn nữa để đạt được những thứ như trạng thái đơn hàng. Tuy nhiên, những cập nhật và lựa chọn đó bạn sẽ cần phải làm để in ra hóa đơn hoặc tạo các báo cáo quản lý sẽ lớn hơn chèn gốc.
paxdiablo

Hãy nghĩ đến Amazon - Hàng nghìn đơn hàng được tạo ra mỗi giờ.
người dùng

9
@buffer, vâng, nhưng một lần nữa, mỗi đơn đặt hàng gần như chắc chắn sẽ được truy vấn nhiều lần để thực hiện (ví dụ) đóng gói, thanh toán, cập nhật trạng thái, phân tích kinh doanh, v.v. Số lần tạo tuyệt đối ít quan trọng hơn tỷ lệ giữa lần tạo và lần đọc.
paxdiablo

1
Quan điểm của tôi là, insertsẽ quan trọng nếu nó được thực hiện hàng nghìn lần mỗi giờ. Bạn không thể đơn giản bỏ qua nó chỉ vì tỷ lệ so insertvới select<1. Trong trường hợp này, khách hàng quan tâm đến việc mất bao nhiêu thời gian để đặt hàng.
người dùng

19

Không cần khóa thay thế cho các bảng liên kết.

Một PK trên (col1, col2) và một chỉ mục duy nhất khác trên (col2, col1) là tất cả những gì bạn cần

Trừ khi bạn sử dụng ORM không thể đối phó và ra lệnh thiết kế DB cho bạn ...

Chỉnh sửa: Tôi đã trả lời tương tự ở đây: SQL: Bạn có cần khóa chính tự động tăng dần cho Nhiều-Nhiều bảng không?


3
Bạn có thể OK với chỉ mục dups trên col2 thay vì chỉ mục duy nhất trên (col2, col1). Ưu điểm của chỉ mục hai cột là nó cho phép quét chỉ chỉ mục trên một mình col2 hoặc trên cả col1 và col2 (mặc dù chỉ mục khác, trên (col1, col2) cũng xử lý trường hợp 'cả hai'). Nhược điểm là dung lượng lưu trữ bổ sung cần thiết cho cột phụ. Điều này thường không đáng kể, vì vậy lời khuyên là không khủng khiếp. Tuy nhiên, nếu col1 và col2 lớn hoặc có kích thước rất khác nhau, bạn có thể tiết kiệm cho mình một số không gian mà không ảnh hưởng đến hiệu suất bằng cách chọn chỉ mục thứ hai trên cột ngắn hơn.
Jonathan Leffler

@gbn: Chỉ mục thứ hai trên (col2, col1) không cần phải là duy nhất, phải không?
người dùng

1
đặt một chỉ số duy nhất trên (col1, col2) sau khi nó đã là một PK là hoàn toàn không cần thiết
Don Cheadle

@mmcrae: chúng ta đang làm điều đó ở đâu?
gbn

2
@mmcrae: Nhận xét của bạn là "đặt một chỉ mục duy nhất trên (col1, col2) ..". Thứ tự cột trong một chỉ mục quan trọng. (col2, col1)không (col1, col2). PK của (col1, col2)có thể không phù hợp với tất cả các truy vấn và tạo ra các bản quét, do đó, mặt trái của điều đó sẽ cải thiện hiệu suất vì nó cho phép tìm kiếm nơi col2 tốt hơn. Ví dụ, xác thực FK khi bảng có col2 bị xóa. Bảng con sẽ được kiểm tra
gbn

12

Có thể cần một khóa chính tăng dần nếu bảng được tham chiếu. Có thể có các chi tiết trong bảng nhiều-nhiều cần được kéo lên từ bảng khác bằng cách sử dụng khóa chính tăng dần.

ví dụ

PartDevice
----------
ID (PK/auto-increment)
PartID (FK)
DeviceID (FK)
Other Details

Thật dễ dàng để kéo 'Chi tiết khác' bằng PartDevice.ID làm FK. Do đó, việc sử dụng khóa chính tăng dần là cần thiết.


1
Cảm ơn! Tôi đã đi đến câu trả lời khi tôi đang tìm kiếm tình huống gần giống như bạn đã mô tả. Nhưng bạn đã trôi tuột khỏi câu đầu tiên của mình bằng cách thêm "Các chi tiết khác". Điều gì sẽ xảy ra nếu tôi có một bảng ánh xạ nhiều đến nhiều, mà tôi cần tham chiếu đến từ một bảng khác? Có nghĩa là, bảng ánh xạ nhiều đến nhiều không lưu trữ bất kỳ thông tin nào khác ... Dù sao thì cột ID bổ sung cũng có ý nghĩa? Nếu không, làm thế nào để tham chiếu đến một bản ghi của bảng ánh xạ?
misanthrop

Có hai tùy chọn ở đây, bạn có thể sử dụng khóa ghép làm khóa ngoại từ bảng tham chiếu của mình (điều này thêm một cột bổ sung vào bảng mới của bạn) hoặc bạn có thể tạo một cột id cho bảng ánh xạ và đặt ràng buộc duy nhất cho phức hợp ban đầu khóa chính trong khi cột id mới sẽ trở thành khóa chính.
Vočko

6

Cách ngắn nhất và trực tiếp nhất mà tôi có thể trả lời câu hỏi của bạn là nói rằng sẽ có tác động đến hiệu suất nếu hai bảng bạn đang liên kết không có khóa chính tuần tự. Như bạn đã nêu / trích dẫn, chỉ mục cho bảng liên kết sẽ bị phân mảnh hoặc DBMS sẽ làm việc nhiều hơn để chèn các bản ghi nếu bảng liên kết không có khóa chính tuần tự của riêng nó. Đây là lý do mà hầu hết mọi người đặt một khóa chính tăng dần theo thứ tự trên các bảng liên kết.


2

Vì vậy, có vẻ như nếu công việc DUY NHẤT là liên kết hai bảng, thì PK tốt nhất sẽ là PK cột kép.

Nhưng nếu nó phục vụ các mục đích khác thì hãy thêm một NDX khác làm PK với khóa ngoại và chỉ mục duy nhất thứ hai.

Chỉ mục hoặc PK là cách tốt nhất để đảm bảo không có bản sao. PK cho phép các công cụ như Microsoft Management Studio thực hiện một số công việc (tạo chế độ xem) cho bạ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.