2013-07-29 38 views
5

Tôi đã truy vấn này để bắt đầu với:Làm thế nào để làm cho JOINS nhanh hơn?

SELECT DISTINCT spentits.* 
FROM `spentits` 
WHERE (spentits.user_id IN 
     (SELECT following_id 
      FROM `follows` 
      WHERE `follows`.`follower_id` = '44' 
      AND `follows`.`accepted` = 1) 
     OR spentits.user_id = '44') 
ORDER BY id DESC 
LIMIT 15 OFFSET 0 

truy vấn này có 10ms để thực thi.

Nhưng một khi tôi thêm một đơn giản tham gia:

SELECT DISTINCT spentits.* 
FROM `spentits` 
LEFT JOIN wishlist_items ON wishlist_items.user_id = 44 AND wishlist_items.spentit_id = spentits.id 
WHERE (spentits.user_id IN 
     (SELECT following_id 
      FROM `follows` 
      WHERE `follows`.`follower_id` = '44' 
      AND `follows`.`accepted` = 1) 
     OR spentits.user_id = '44') 
ORDER BY id DESC 
LIMIT 15 OFFSET 0 

này thực hiện thời gian tăng 11x. Bây giờ phải mất khoảng 120ms để thực thi. Điều thú vị là nếu tôi xóa một trong các điều khoản LEFT JOINhoặc số ORDER BY id DESC, hãy quay lại 10ms.

Tôi mới sử dụng cơ sở dữ liệu nên tôi không hiểu điều này. Tại sao việc xóa một trong hai mệnh đề này lại tăng tốc độ lên 11x? Và làm thế nào tôi có thể giữ nó như là nhưng làm cho nó nhanh hơn?

Tôi có chỉ mục trên spentits.user_id, follows.follower_id, follows.accepted và trên primary ids của mỗi bảng.

GIẢI THÍCH:

1 PRIMARY spentits index index_spentits_on_user_id PRIMARY 4 NULL 15 Using where; Using temporary 
1 PRIMARY wishlist_items ref index_wishlist_items_on_user_id,index_wishlist_items_on_spentit_id index_wishlist_items_on_spentit_id 5 spentit.spentits.id 1 Using where; Distinct 
2 SUBQUERY follows index_merge index_follows_on_follower_id,index_follows_on_following_id,index_follows_on_accepted 

index_follows_on_follower_id,index_follows_on_accepted 5,2 NULL 566 Using intersect(index_follows_on_follower_id,index_follows_on_accepted); Using where 
+1

EXPLAIN PLAN hiển thị những gì? –

+0

@DavidJashi được cập nhật với GIẢI THÍCH – 0xSina

Trả lời

2

Bạn nên có chỉ số cũng trên:

wishlist_items.spentit_id

Bởi vì bạn đang tham gia trên cột đó

+0

Rất tiếc, tôi quên liệt kê nó, nhưng tôi đã lập chỉ mục. – 0xSina

0

Các LEFT JOIN là eas y để giải thích: Một sản phẩm chéo của tất cả các mục chống lại tất cả các mục khác được thực hiện. Các điều kiện tham gia (trong trường hợp của bạn: Lấy tất cả các mục bên trái và tìm các mục phù hợp ở bên phải) được áp dụng sau đó. Vì vậy, nếu bảng chi tiêu của bạn là lớn, nó sẽ mất máy chủ một thời gian. Đề nghị bạn loại bỏ truy vấn phụ của bạn và thực hiện ba lần tham gia. Bắt đầu với bảng nhỏ nhất để tránh lượng dữ liệu lớn.

+1

'Một sản phẩm chéo của tất cả các mục chống lại tất cả các mục khác được thực hiện' - Đó là CROSS JOIN, không LEFT JOIN –

+0

Ngoài ra, làm 2 JOINS (tham gia vào sau thay vì os subquery) giết hiệu suất. Mất khoảng 350 ms để thực thi. – 0xSina

0

Trong ví dụ thứ hai, chọn lọc phụ sẽ chạy cho mỗi spendits.user_id.

Nếu bạn viết là như thế này nó sẽ nhanh hơn vì subselect chạy một lần:

SELECT DISTINCT spentits.* 
FROM `spentits`, (SELECT following_id 
      FROM `follows` 
      WHERE `follows`.`follower_id` = '44' 
      AND `follows`.`accepted` = 1) 
     OR spentits.user_id = '44') as `follow` 
LEFT JOIN wishlist_items ON wishlist_items.user_id = 44 AND wishlist_items.spentit_id = spentits.id 
WHERE (spentits.user_id IN 
     (follow) 
ORDER BY id DESC 
LIMIT 15 OFFSET 0 

Như bạn có thể thấy subselect chuyển đến FROM-một phần của truy vấn và tạo ra một tabel tưởng tượng (hoặc xem). Tabel tưởng tượng này là chế độ xem nội tuyến.

THAM GIA và lượt xem nội tuyến nhanh hơn mỗi lần so với chọn lựa trong phần WHERE.

+0

Bắt 'Cột không xác định' theo 'trong' ở đâu khoản '' – 0xSina

+0

Bạn nói đúng. Có lỗi với toán tử '(' và IN không khớp với tab wiht. – Shockergnomm

+0

Hãy thử này xin vui lòng: CHỌN spentits DISTINCT * FROM 'spentits', (SELECT following_id FROM' follows' ĐÂU 'follows'.'follower_id' = '44' VÀ' follows'.'accepted' = 1.) HOẶC spentits.user_id = '44') là 'follow' LEFT JOIN wishlist_items ON wishlist_items.user_id = 44 VÀ wishlist_items.spentit_id = spentits.id ĐÂU spentits.user_id = follow.following_id ORDER BY id DESC LIMIT 15 OFFSET 0 – Shockergnomm

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