2013-07-22 35 views
5

Tôi có hai bảng:NHÓM THEO TỪ khóa chính hoặc khóa chính?

user 
======= 
id 
name 
class 

marks 
======= 
id 
user_id 
sub_id 
mark 

bảng người dùng chứa các chi tiết của người dùng (sinh viên) dấu bảng chứa những dấu tích của một sinh viên trong các môn học khác nhau với id chủ đề

Tôi muốn lấy tên, lớp và tổng số điểm từ các bảng này.

Tôi có hai câu hỏi:

1. SELECT name, class, SUM(mark) AS total FROM user 
    LEFT JOIN marks ON marks.user_id = user.id 
    GROUP BY marks.user_id 
    ///Here in GROUP BY I have used foreign key (marks.user_id) 

2. SELECT name, class, SUM(mark) AS total FROM user 
    LEFT JOIN marks ON marks.user_id = user.id 
    GROUP BY user.id 
    ///Here in GROUP BY I have used primary key (user.id) 

Cả hai mang lại cho tôi yêu cầu dữ liệu. Câu hỏi của tôi là tôi nên sử dụng cái nào?

Có quy tắc nào cho biết bạn nên sử dụng khóa chính trong nhóm bằng OR khóa ngoại trong nhóm bằng HOẶC một cái gì đó như thế?

+1

thử chạy truy vấn 'user.id' không có giá trị khớp cho' marks.user_id'. và xem điều gì xảy ra .. –

+2

'Giải thích' nói gì về cả hai truy vấn? –

+0

@ 491243: Hãy để tôi kiểm tra điều đó. –

Trả lời

3

Bạn nên sử dụng nhóm phiên bản 2 bằng khóa chính. Nói chung tốt hơn là đặt hàng và nhóm theo các câu lệnh dựa trên cột (s) của bảng chính chứ không phải các cột được nối. Nếu bạn làm theo thứ tự hoặc nhóm theo các cột trong bảng đã tham gia, MySQL phải tạo các bảng tạm thời dựa trên dữ liệu của bạn có thể dễ dàng đi vào đĩa và kết thúc nút cổ chai hiệu suất đáng kể.

Run những giải thích cho hai truy vấn để xem những gì tôi đang nói về:

EXPLAIN SELECT name, SUM(mark) AS total FROM users 
    LEFT JOIN marks ON marks.user_id = users.id 
    GROUP BY marks.user_id; 

EXPLAIN SELECT name, SUM(mark) AS total FROM users 
    LEFT JOIN marks ON marks.user_id = users.id 
    GROUP BY users.id; 

Cùng có thể được tìm thấy ở đây: http://sqlfiddle.com/#!2/a8ece/6

+0

Cảm ơn tôi nghĩ đây là câu trả lời tôi muốn. :) –

0

vì khóa chính là chỉ mục duy nhất. nhóm bằng (Key chính)

không giảm số lượng dòng trong kết quả của bạn

vì vậy tôi nghĩ rằng bạn có thể sử dụng nhóm bằng (khoá ngoại)

6

Với bạn đã làm một trái tham gia, bạn nên sử dụng Truy vấn thứ hai là marks.user_id có thể là null

+0

Và nếu marks.user_id không phải là null. Tôi đang nói về hiệu suất, khi tôi sẽ có một dữ liệu khổng lồ. –

2

Tôi khuyên bạn nên sử dụng câu lệnh thứ hai vì có sự khác biệt về hiệu suất giữa chỉ mục khóa chính và bất kỳ chỉ mục trùng lặp nào khác. Rất có thể truy vấn phổ biến nhất của bạn vào bảng đó sẽ là tìm hiểu xem người dùng có ở một điểm nhất định hay không, và truy vấn đó sẽ hoạt động nhanh trừ khi marks.user_id có thể rỗng.

1

Khi tôi chạy SQL sau đây:

DESCRIBE SELECT name, class, SUM(mark) AS total FROM user 
LEFT JOIN marks ON marks.user_id = user.id 
GROUP BY marks.user_id; 

MySQL cho biết nó sử dụng filesort cho bảng người dùng và không có khóa nào được sử dụng cho bảng, và khi tôi chạy như sau:

DESCRIBE SELECT name, class, SUM(mark) AS total FROM user 
LEFT JOIN marks ON marks.user_id = user.id 
GROUP BY user.id; 

Bây giờ MySQL cho biết nó sử dụng các khóa cho cả hai bảng (thay vì sử dụng filesort). Vì vậy, tôi nghĩ rằng, thứ hai nên được thực hành được khuyến cáo như filesort có thể làm suy giảm hiệu suất.

Các vấn đề liên quan