Cột trùng lặp cho truy vấn nhanh hơn?


30

Tiêu đề không có ý nghĩa quá nhiều, nhưng tôi không thể nghĩ rằng một tiêu đề tốt hơn cho vấn đề này.

Tôi có các bảng sau

Dự án

  • ID
  • Tên

Khách hàng

  • ID
  • id_project
  • Tên

Thanh toán

  • ID
  • khách hàng
  • ngày
  • tổng

Khi người dùng vào hệ thống, anh ta sẽ có quyền truy cập vào một dự án nhất định. Bây giờ, tôi muốn liệt kê tất cả các khoản thanh toán cho dự án đó và nó sẽ khá dễ dàng:

SELECT FROM payments where id_customer in (SELECT id from customers where id_project = 5)

Câu hỏi của tôi là: nếu không tốt hơn khi thêm cột id_project vào bảng thanh toán theo cách này thì các truy vấn sẽ dễ dàng và nhanh hơn.


1
vì vậy truy vấn không phải là vấn đề đối với các RDBMS hiện đại (hoặc tốt hơn, sử dụng phép nối).
garik

4
Đồng ý, nhận một kế hoạch truy vấn cho subselect vs tham gia và xem cái nào tốt hơn
Gaius

1
Tôi nghĩ rằng bài đăng SO này đáng để tìm kiếm, vì @igor đã đề cập về việc sử dụng THAM GIA hoặc IN
CoderHawk

Câu trả lời:


52

Có vẻ như bạn đang hỏi nếu không chuẩn hóa có ý nghĩa.

Không chuẩn hóa là quá trình cố gắng tối ưu hóa hiệu suất đọc của cơ sở dữ liệu bằng cách thêm dữ liệu dư thừa hoặc bằng cách nhóm dữ liệu. Trong một số trường hợp, việc không chuẩn hóa giúp che đậy sự thiếu hiệu quả vốn có trong phần mềm cơ sở dữ liệu quan hệ. Một cơ sở dữ liệu chuẩn hóa quan hệ áp đặt tải truy cập lớn lên lưu trữ dữ liệu vật lý ngay cả khi nó được điều chỉnh tốt cho hiệu suất cao.

Câu trả lời luôn là "nó phụ thuộc", vì vậy đây là quy tắc của tôi:

Nếu ...

  • lượng dữ liệu không lớn
  • bạn đã không làm rất nhiều việc tham gia
  • và / hoặc hiệu suất cơ sở dữ liệu hiện không phải là nút cổ chai

sau đó lại bình thường . Có, việc không chuẩn hóa nhanh hơn, nhưng điều đó cũng có nghĩa là bạn có dữ liệu dư thừa trong hệ thống - dữ liệu phải được duy trì và giữ đồng bộ. Không còn "một nguồn" cho dữ liệu đó, mà nhiều nguồn có thể sai lệch. Điều này là rủi ro theo thời gian, vì vậy bạn không nên làm điều đó trừ khi bạn có lý do rất chính đáng để làm điều đó, được hỗ trợ bởi một số điểm chuẩn.

Tôi sẽ chỉ không chuẩn hóa khi ...

  • lượng dữ liệu rất lớn
  • tham gia rất tốn kém và bạn phải thực hiện rất nhiều trong số chúng để nhận được các truy vấn tầm thường
  • hiệu suất cơ sở dữ liệu là một nút cổ chai và / hoặc bạn muốn đi càng nhanh càng tốt

Tham gia rất nhanh trên phần cứng hiện đại, nhưng chúng là không bao giờ miễn phí.


9

Bạn nên viết lại truy vấn dưới dạng:

SELECT payments.*
FROM   customers
JOIN   payments 
ON     payments.id_customer = customers.id
WHERE  customers.id_project = 5

Mặc dù điều này có vẻ ít súc tích hơn và một trình hoạch định truy vấn tốt sẽ thấy những gì bạn đang cố gắng thực hiện và chạy truy vấn phụ tương quan của bạn như tham gia ở trên thay vào đó, một trình hoạch định truy vấn xấu có thể sẽ thực hiện quét chỉ mục payments.id_customer(giả sử bạn có một chỉ mục có liên quan ) (hoặc tệ hơn là quét bảng) thay vì thực hiện mọi thứ theo cách hiệu quả hơn. Ngay cả một trình hoạch định truy vấn tốt cũng có thể không thấy tối ưu hóa nếu sự sắp xếp của truy vấn này được gói trong một cái gì đó phức tạp hơn. Thể hiện mối quan hệ dưới dạng tham gia thay vì truy vấn phụ có thể tạo ra nhiều sự khác biệt hơn là thay đổi cấu trúc dữ liệu của bạn.

Như Jeff nói, bất kỳ sự không chuẩn hóa nào cũng cần được xem xét cẩn thận - nó có thể mang lại hiệu suất tăng dễ dàng, đặc biệt cho một số mục đích báo cáo, nhưng có thể dẫn đến sự không nhất quán do lỗi trong logic kinh doanh hỗ trợ.

Như một lưu ý phụ: Rõ ràng tôi không biết doanh nghiệp của bạn vì vậy tôi có thể thiếu một cái gì đó, nhưng các mối quan hệ trên bàn của bạn có vẻ kỳ lạ đối với tôi. Họ ngụ ý rằng bạn không bao giờ có thể có nhiều hơn một dự án với cùng một khách hàng thường không đúng với kinh nghiệm của tôi, ít nhất là trong một khoảng thời gian dài.

customer     project      payment
--------     --------     -------
                          pa_id
             pr_id    <-- payment
cu_id    <-- customer     

hoặc nếu ít được chuẩn hóa (mặc dù tôi nghi ngờ điều đó là cần thiết):

customer     project      payment
--------     --------     --------
                          pa_id
             pr_id    <-- payment
cu_id    <-- customer 
           `------------- customer    

Tất nhiên là vẫn giảm khả năng dự án chung với hai khách hàng ...


3
Nguyên tắc đầu tiên của hiệu suất: Không bao giờ sử dụng * trong sản xuất!
Brian Ballsun-Stanton

@Brian: điểm rất hợp lệ. Và cũng như các hàm ý hiệu suất tiềm năng tránh * trong các mệnh đề được chọn cũng tránh được các vấn đề với thứ tự cột trong chế độ xem theo quan điểm trong MSSQL nếu sys.depends bị hết kilter do DROP VIEW+ CREATE VIEWđược sử dụng thay vì ALTER VIEW.
David Spillett

@Brian tôi đặt * để dễ viết.
Gabriel Solomon

Dự án được coi là một ứng dụng độc lập với tên miền và thuộc về các khách hàng khác nhau nên khách hàng không thể có cùng một tài khoản trên các dự án khác nhau
Gabriel Solomon

4

Trong một số cơ sở dữ liệu, bạn có khả năng tạo "Chế độ xem được vật chất hóa" thay vì VIEWS phức tạp với lượng dữ liệu lớn, dựa trên truy vấn phức tạp. Điều này có thể được sử dụng để tránh sự không chuẩn hóa trong hệ thống ứng dụng đã phát triển trong lịch sử. Nếu bạn quyết định sử dụng " Chế độ xem được vật chất hóa "bạn phải có ý tưởng rõ ràng về các phương thức làm mới và dung lượng lưu trữ sẽ được sử dụng bởi Chế độ xem được vật chất hóa ...

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.