Foreign Key có cải thiện hiệu năng truy vấn không?


149

Giả sử tôi có 2 bảng, Sản phẩm và Danh mục sản phẩm. Cả hai bảng có mối quan hệ trên CategoryId. Và đây là truy vấn.

SELECT p.ProductId, p.Name, c.CategoryId, c.Name AS Category
FROM Products p
INNER JOIN ProductCategories c ON p.CategoryId = c.CategoryId
WHERE c.CategoryId = 1;

Khi tôi tạo kế hoạch thực hiện, bảng ProductC loại thực hiện tìm kiếm chỉ mục cụm, đó là như mong đợi. Nhưng đối với Sản phẩm bảng, nó thực hiện quét chỉ mục cụm, điều này khiến tôi nghi ngờ. Tại sao FK không giúp cải thiện hiệu suất truy vấn?

Vì vậy, tôi phải tạo chỉ mục trên Products.C CategoryId. Khi tôi tạo kế hoạch thực hiện lại, cả hai bảng thực hiện tìm kiếm chỉ mục. Và ước tính chi phí cây con được giảm rất nhiều.

Câu hỏi của tôi là:

  1. Bên cạnh FK giúp hạn chế mối quan hệ, nó có hữu ích nào khác không? Nó có cải thiện hiệu năng truy vấn không?

  2. Tôi có nên tạo chỉ mục trên tất cả các cột FK (thích Sản phẩm. Thể loại) trong tất cả các bảng không?

Câu trả lời:


186

Khóa ngoại là một công cụ toàn vẹn tham chiếu, không phải là một công cụ hiệu suất. Ít nhất là trong SQL Server, việc tạo FK không tạo ra một chỉ mục liên quan và bạn nên tạo các chỉ mục trên tất cả các trường FK để cải thiện thời gian tra cứu.


40
Mô hình tốt (nói chung) thực hiện tốt hơn.
Kenny Evitt

10
"Khóa ngoại là một công cụ toàn vẹn quan hệ" - vui lòng sử dụng từ 'quan hệ' một cách cẩn thận. Khóa ngoại là một khái niệm cơ sở dữ liệu, một tay ngắn cho một ràng buộc toàn vẹn tham chiếu. Chúng không phải là một phần của mô hình quan hệ. Tôi giả sử bạn đã mắc lỗi đánh máy.
onedaywhen

7
@Kenny Thường thì có, nhưng đôi khi một mô hình tốt hơn có giá cao hơn. Trường hợp tại điểm: khóa ngoại gây ra nhiều xử lý xảy ra, không phải ít hơn.
Hans

8
khóa ngoại làm cải thiện hiệu suất, ít nhất là trong MySQL. Hơn nữa, bạn đã đúng, việc tạo FK không tạo ra một chỉ mục; việc tạo ra một FK đòi hỏi phải có một chỉ số
Félix Gagnon-Grenier

15
Câu trả lời này khá vô dụng vì nó không trả lời được câu hỏi. Thật tuyệt khi biết rằng khóa ngoại không nhằm có tác động (tích cực) đến hiệu suất, nhưng câu hỏi liên quan đến thực tế, không phải ý định.
Giăng

58

Khóa ngoại có thể cải thiện (và làm tổn thương) hiệu suất

  1. Như đã nêu ở đây: Khóa ngoại tăng hiệu suất

  2. Bạn phải luôn tạo các chỉ mục trên các cột FK để giảm tra cứu. SQL Server không làm điều này tự động.

Biên tập

Vì liên kết bây giờ dường như đã chết (kudos cho Chris để ý) , sau đây cho thấy ý chính tại sao các khóa ngoại có thể cải thiện (và làm tổn thương) hiệu suất.

Khóa ngoại có thể cải thiện hiệu suất

Ràng buộc khóa ngoài cải thiện hiệu suất tại thời điểm đọc dữ liệu nhưng đồng thời nó làm chậm hiệu suất tại thời điểm chèn / sửa đổi / xóa dữ liệu.

Trong trường hợp đọc truy vấn, trình tối ưu hóa có thể sử dụng các ràng buộc khóa ngoài để tạo các kế hoạch truy vấn hiệu quả hơn vì các ràng buộc khóa ngoài là các quy tắc được khai báo trước. Điều này thường liên quan đến việc bỏ qua một phần của kế hoạch truy vấn vì ví dụ trình tối ưu hóa có thể thấy rằng do ràng buộc khóa ngoài, không cần thiết phải thực thi phần cụ thể đó của kế hoạch.


3
Đây là một liên kết chi tiết các cách mà họ có thể làm giảm hiệu suất devx.com/getHelpOn/10MinuteSolution/16595/0/page/2
cmsjr

3
Điều đó có ý nghĩa nhưng bạn sẽ chỉ gặp phải vấn đề này với một tuyên bố xóa lớn. Có lẽ kết luận là trong các môi trường OLAP, các FK không được lập chỉ mục sẽ cải thiện hiệu suất trong khi trong các môi trường OLTP, nó sẽ làm giảm hiệu suất.
Lieven Keersmaekers

1
Liên kết trong Câu trả lời này đã chết. Điều này thật đáng tiếc vì đây là đối số duy nhất ở đây để cải thiện hiệu suất của FK.
Chris Moschini

1
@ChrisMoschini - Tôi không nhận thấy bình luận của bạn cho đến bây giờ. Như bạn đã đề cập, liên kết đã chết nhưng ý chính của nó được đề cập trong liên kết mới (có chi tiết) tôi đã đăng.
Lieven Keersmaekers

2
Liên kết Wayback Machine cho Win! Bài viết cũng có thể được tìm thấy trên SQLMag.com, ở đây .
John Eisbrener

15

Khóa ngoại là một khái niệm DBMS để đảm bảo tính toàn vẹn của cơ sở dữ liệu.

Bất kỳ ý nghĩa / cải tiến hiệu suất nào cũng sẽ được dành riêng cho công nghệ cơ sở dữ liệu đang được sử dụng và là thứ yếu đối với mục đích của khóa ngoại.

Đó là một thực tiễn tốt trong SQL Server để đảm bảo rằng tất cả các khóa ngoại có ít nhất một chỉ mục không được nhóm trên chúng.

Tôi hy vọng điều này sẽ làm sáng tỏ mọi thứ cho bạn nhưng xin vui lòng yêu cầu thêm chi tiết.


9
@Kenny Evitt nếu bạn không có tính toàn vẹn, dữ liệu của bạn là vô ích. Tôi thấy rằng bán rất dễ dàng.
HLGEM

@HLGEM Nhận được một lỗi 404 thỉnh thoảng vẫn còn khá khó chịu. Có thông lượng đặc biệt để trả lại bằng cách sử dụng các tài nguyên rẻ hơn và các hệ thống ít phức tạp hơn, giờ đây cũng bán rất dễ dàng. Bạn có thể quan tâm đến định lý CAP .
Daniel Dinnyes

8
@Daniel Dinnyes, tính toàn vẹn dữ liệu không phải là về lỗi 404. Đó là về việc có dữ liệu có thể sử dụng. Chẳng hạn như việc không mất đơn đặt hàng và dữ liệu tài chính cho các báo cáo vì sự bất tài của các nhà phát triển. KHÔNG CÓ LÝ DO cho việc không sử dụng khóa ngoại.
HLGEM

2
Tôi đồng ý với HLGEM. Để mã của bạn xử lý tính toàn vẹn không phải lúc nào cũng là một ý tưởng hay. Dữ liệu thường được sử dụng để đưa ra quyết định, nhưng nếu dữ liệu bị hỏng, thì quyết định sẽ không chính xác.
Lepe

1
"Khóa ngoại là một công cụ toàn vẹn quan hệ" - vui lòng sử dụng từ 'quan hệ' một cách cẩn thận. Khóa ngoại là một khái niệm cơ sở dữ liệu, một tay ngắn cho một ràng buộc toàn vẹn tham chiếu. Chúng không phải là một phần của mô hình quan hệ. Tôi giả sử bạn đã mắc lỗi đánh máy.
onedaywhen

4

Đặt cược hiệu suất tốt nhất của bạn là sử dụng Chỉ mục trên các lĩnh vực bạn sử dụng thường xuyên. Nếu bạn sử dụng SQL Server, bạn có thể sử dụng profiler để cấu hình một cơ sở dữ liệu cụ thể và lấy tệp xuất ra và sử dụng trình hướng dẫn điều chỉnh để nhận các đề xuất về nơi đặt các chỉ mục của bạn. Tôi cũng thích sử dụng profiler để tuôn ra các thủ tục được lưu trữ lâu dài, tôi có một danh sách mười tội phạm tồi tệ nhất tôi xuất bản mỗi tuần, giữ cho mọi người trung thực: D.


3

Bạn có thể sử dụng nó để giúp làm cho một truy vấn hiệu quả hơn. Nó cho phép bạn cấu trúc lại các truy vấn trong SQL Server để sử dụng một phép nối ngoài thay vì một truy vấn bên trong để loại bỏ các máy chủ sql cần phải kiểm tra xem có cột nào trong cột không. Bạn không cần phải đưa vòng loại đó vào vì mối quan hệ khóa ngoại đã tạo ra điều đó cho bạn.

Vậy đây:

    select p.ProductId, p.Name, c.CategoryId, c.Name AS Category 
from Products p inner join ProductCategories c on p.CategoryId = c.CategoryIdwhere c.CategoryId = 1;

Trở thành này:

SELECT p.ProductId, p.Name, c.CategoryId, c.Name AS Category 
FROM ProductCategories c 
LEFT OUTER JOIN Products P ON
c.CategoryId = p.CategoryId 
WHERE c.CategoryId = 1;

Điều này sẽ không nhất thiết phải thực hiện một hiệu suất lớn trong các truy vấn nhỏ, nhưng khi các bảng trở nên lớn, nó có thể hiệu quả hơn.


3
Không chỉ các kết nối bên ngoài thường kém hiệu quả hơn các liên kết bên trong ( stackoverflow.com/a/2726683/155892 ), giờ đây các truy vấn của bạn bị sai lệch: bạn đang dựa vào cơ sở dữ liệu để biến các kết nối bên ngoài của bạn thành các liên kết bên trong (khôi phục hiệu suất) thay vì chỉ làm điều đó một cách rõ ràng
Mark Sowul

2

Đối với MySQL 5.7, nó chắc chắn có thể tăng tốc các truy vấn liên quan đến nhiều tham gia một cách tuyệt vời!

Tôi đã sử dụng 'giải thích' để hiểu truy vấn của mình và thấy rằng tôi đã tham gia 4-5 bảng - nơi không có khóa nào được sử dụng. Tôi không làm gì ngoài việc thêm khóa ngoại vào các bảng này và kết quả là giảm 90% thời gian tải. Các truy vấn mất> 5s giờ mất 500ms hoặc ít hơn.

Đó là một cải tiến ENORMOUS!

VÀ, như những người khác đã đề cập, bạn nhận được tiền thưởng bổ sung để đảm bảo tính toàn vẹn quan hệ.

Ngoài ra, đảm bảo tính toàn vẹn tham chiếu cũng có lợi ích hiệu suất riêng. Nó có hiệu lực thứ hai để đảm bảo rằng các bảng có khóa ngoại được 'cập nhật' với bảng ngoại. Giả sử bạn có bảng người dùng và bảng nhận xét và bạn đang thực hiện một số thống kê trên bảng nhận xét. Có lẽ nếu bạn khó xóa người dùng, bạn cũng không muốn bình luận của họ nữa.


Các bảng có các chỉ mục cần thiết để tạo khóa ngoại trước khi bạn thêm chúng không?
George

1

Thêm khóa ngoại trong bảng sẽ không cải thiện hiệu suất, chỉ cần nói rằng nếu bạn đang chèn một bản ghi trong cơ sở dữ liệu bảng ProductC loại sẽ cố gắng tìm cột khóa ngoại có giá trị tồn tại trong giá trị khóa chính của bảng sản phẩm, điều này tra cứu, hoạt động là chi phí trên cơ sở dữ liệu của bạn mỗi khi bạn thêm một mục mới trong bảng ProductC chuyên mục. Vì vậy, bằng cách thêm khóa ngoại sẽ không cải thiện hiệu suất cơ sở dữ liệu của bạn nhưng nó sẽ quan tâm đến tính toàn vẹn của cơ sở dữ liệu của bạn. Có, nó sẽ cải thiện hiệu suất của db của bạn nếu bạn đang kiểm tra tính toàn vẹn bằng khóa ngoại thay vì chạy nhiều truy vấn để kiểm tra bản ghi đang tồn tại trong cơ sở dữ liệu trong chương trình của bạn.


0

Tôi không biết nhiều về máy chủ SQL, nhưng trong trường hợp của Oracle, việc có một cột khóa ngoại làm giảm hiệu suất tải dữ liệu. Đó là bởi vì cơ sở dữ liệu cần kiểm tra tính toàn vẹn dữ liệu cho mỗi lần chèn. Và vâng, như đã được đề cập, có một chỉ mục trên cột khóa ngoại là một cách làm tốt.


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.