2009-11-27 31 views
11

Vì vậy ... cái nào nhanh hơn (giá trị NULl không phải là vấn đề) và được lập chỉ mục.Còn lại THAM GIA nhanh hơn hoặc Tham gia bên trong nhanh hơn?

SELECT * FROM A 
    JOIN B b ON b.id = a.id 
    JOIN C c ON c.id = b.id 
WHERE A.id = '12345' 

Sử dụng trái tham gia:

SELECT * FROM A 
LEFT JOIN B ON B.id=A.bid 
LEFT JOIN C ON C.id=B.cid 
WHERE A.id = '12345' 

Đây là truy vấn thực tế Dưới đây là .. cả hai trở lại cùng một kết quả

Query (0.2693sec) : 
    EXPLAIN EXTENDED SELECT * 
    FROM friend_events, zcms_users, user_events, 
    EVENTS WHERE friend_events.userid = '13006' 
    AND friend_events.state =0 
    AND UNIX_TIMESTAMP(friend_events.t) >=1258923485 
    AND friend_events.xid = user_events.id 
    AND user_events.eid = events.eid 
    AND events.active =1 
    AND zcms_users.id = user_events.userid 

EXPLAIN 

    id select_type table type possible_keys key key_len ref rows Extra 
    1 SIMPLE zcms_users ALL PRIMARY NULL NULL NULL 43082 
    1 SIMPLE user_events ref PRIMARY,eid,userid userid 4 zcms_users.id 1 
    1 SIMPLE events eq_ref PRIMARY,active PRIMARY4 user_events.eid 1 Using where 
    1 SIMPLE friend_events eq_ref PRIMARY PRIMARY 8 user_events.id,const 1 Using where 



    LEFTJOIN QUERY: (0.0393 sec) 

    EXPLAIN EXTENDED SELECT * 
    FROM `friend_events` 
    LEFT JOIN `user_events` ON user_events.id = friend_events.xid 
    LEFT JOIN `events` ON user_events.eid = events.eid 
    LEFT JOIN `zcms_users` ON user_events.userid = zcms_users.id 
    WHERE (
    events.active =1 
    ) 
    AND (
    friend_events.userid = '13006' 
    ) 
    AND (
    friend_events.state =0 
    ) 
    AND (
    UNIX_TIMESTAMP(friend_events.t) >=1258923485 
    ) 


EXPLAIN 
    id select_type table type possible_keys key key_len ref rows Extra 
    1 SIMPLE friend_events ALL PRIMARY NULL NULL NULL 53113 Using where 
    1 SIMPLE user_events eq_ref PRIMARY,eid PRIMARY 4 friend_events.xid 1 Using where 
    1 SIMPLE zcms_users eq_ref PRIMARY PRIMARY 4 user_events.userid 1 
    1 SIMPLE events eq_ref PRIMARY,active PRIMARY 4 user_events.eid 1 Using where 
+1

Tại sao bạn không chạy cả hai và cho chúng tôi biết điều gì nhanh hơn? – Welbog

+0

Câu hỏi này nên được lặp lại, "Làm thế nào tôi có thể tìm ra truy vấn nào chạy nhanh hơn?" –

+0

Những sự kiện này có trả lại cùng một tập hợp kết quả không? (cột, không phải hàng) – JMD

Trả lời

9

Nó phụ thuộc; chạy cả hai để tìm hiểu; sau đó chạy một 'giải thích chọn' cho một lời giải thích.

Sự khác biệt hiệu suất thực tế có thể dao động từ "hầu như không tồn tại" thành "khá quan trọng" tùy thuộc vào bao nhiêu hàng trong A với id = '12345' có không có hồ sơ phù hợp trong B và C.

Cập nhật (dựa trên các kế hoạch truy vấn đã đăng)

Khi bạn sử dụng INNER JOIN nó không quan trọng (kết quả khôn ngoan, không hiệu suất) với bảng bắt đầu, vì vậy trình tối ưu hóa cố gắng chọn chương trình phù hợp nhất . Dường như bạn có chỉ mục trên tất cả các cột PK/FK thích hợp và bạn không có chỉ mục trên friend_events.userid hoặc có quá nhiều bản ghi với userid = '13006' và không được sử dụng; hoặc cách tối ưu hóa chọn bảng có ít hàng hơn là "cơ sở" - trong trường hợp này là zcms_users.

Khi bạn sử dụng LEFT JOIN nó thì vấn đề (kết quả khôn ngoan) mà bảng bắt đầu bằng; do đó, friend_events được chọn. Bây giờ lý do tại sao phải mất ít thời gian hơn theo cách đó tôi không hoàn toàn chắc chắn; Tôi đoán điều kiện friend_events.userid có ích. Nếu bạn đã thêm một chỉ mục (là nó thực sự varchar, btw? Không phải số?) Trên đó, INNER JOIN của bạn có thể hoạt động khác nhau (và trở nên nhanh hơn) là tốt.

+0

Tôi đã chạy nó. có vẻ như bên trong là chậm hơn. nhưng không phải là bên trong nên bette rthan còn lại tham gia? – Murvinlai

+0

Bạn có thể đăng kết quả "giải thích chọn" cho cả hai truy vấn không? – ChssPly76

2

Sử dụng EXPLAIN để xem gói truy vấn. Nó có lẽ là kế hoạch tương tự cho cả hai trường hợp, vì vậy tôi nghi ngờ nó làm cho nhiều sự khác biệt, giả sử không có hàng nào không khớp. Nhưng đây là hai truy vấn khác nhau vì vậy nó thực sự không có ý nghĩa để so sánh chúng - bạn chỉ nên sử dụng đúng.

Tại sao không sử dụng từ khóa "INNER JOIN" thay vì "LEFT JOIN"?

3

INNER JOIN phải thực hiện kiểm tra thêm để xóa bất kỳ bản ghi nào từ A không có bản ghi khớp trong B và C. Tùy thuộc vào số lượng bản ghi được trả về ban đầu từ A it COULD có tác động.

1

LEFT JOIN hiển thị tất cả dữ liệu từ A và chỉ hiển thị dữ liệu từ B/C chỉ khi điều kiện là đúng. Đối với INNER JOIN, nó phải làm một số kiểm tra thêm trên cả hai tables. Vì vậy, tôi đoán rằng giải thích tại sao LEFT JOIN nhanh hơn.

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