2013-04-09 28 views
13

Tôi có bảng như thế này2 khác nhau truy vấn nhỏ vs 1 truy vấn với subquery

name  | personal_number 
----------------------------------------- 
Jon  | 222 
Alex  | 555 
Jon  | 222 
Jimmy  | 999 

tôi cần có được mọi danh hiệu, mà personal_number repeates trong bảng hơn 1, có nghĩa là kết quả phải:

Jon   
Jon   

Vì vậy, Variant 1):

SELECT name FROM mytable WHERE personal_number IN (
     SELECT personal_number FROM mytable GROUP BY personal_number 
     HAVING COUNT(*) > 1 
) 

Variant 2):

SELECT personal_number FROM mytable GROUP BY personal_number 
     HAVING COUNT(*) > 1 
) 

Sau đó, sử dụng php, personal_numbers lấy tham gia như chuỗi (soemthing như '222', '222' này) và chạy truy vấn khác

SELECT name FROM mytable WHERE personal_number IN(here joined string) 

Biến thể 2 công trình khoảng 10 lần nhanh hơn, so với phiên bản 1, đây là sự ngạc nhiên đối với tôi, tôi đã suy nghĩ rằng một truy vấn sẽ nhanh hơn, nhưng ...

(Trong bảng là 500 000 dòng, cột personal_number không lập chỉ mục)

Vì vậy, những gì bạn có nghĩa là về trường hợp như thế này? tại sao biến thể 2 nhanh hơn nhiều so với biến thể 1?

+2

+1 cho câu hỏi hay và không hỏi trước khi chạy một số kiểm tra điểm chuẩn. – enenen

+2

GIẢI THÍCH về hai truy vấn sẽ hiển thị số –

+0

Nếu tên và số cá nhân phụ thuộc vào nhau, bạn nên mang bảng của bạn đến biểu mẫu bình thường thứ hai – Argeman

Trả lời

4

Dường như các truy vấn phụ rất chậm như đã đề cập trong bài viết này http://www.mysqlperformanceblog.com/2010/10/25/mysql-limitations-part-3-subqueries.

Bạn nên cố gắng tránh các truy vấn con và sử dụng tham gia thay thế.

+0

+1 Đối với một điều tốt đẹp từ mysqlperformanceblog – ITroubs

+0

Trường hợp tương tự cho JOIN trên các bảng có nguồn gốc cũng là một truy vấn phụ?một cái gì đó như 'LEFT JOIN (SELECT * FROM A)' ja' ON ja.ID = t.id' – Starx

0

này cần được nhanh hơn:

SELECT name FROM mytable join (
     SELECT personal_number FROM mytable GROUP BY personal_number 
     HAVING COUNT(*) > 1 
)a using (personel_number) 

Edit: Nếu đây là nhanh hơn so với phiên bản 1, sau đó nó có nghĩa là ở biến thể 1 mysql tái tạo các bảng bên trong cho mỗi bản ghi một lần nữa và một lần nữa.

+2

Điều này không giải thích sự khác biệt về hiệu suất. – Bart

+0

@Bart no, it doesnt. – palindrom

0

Vì việc lập chỉ mục không được thực hiện nên chỉ số 1 chậm, vì nó phải khớp với các số cá nhân từ các số cá nhân được chọn. Nếu việc lập chỉ mục được thực hiện, nó sẽ tiêu tốn ít thời gian hơn trước đó. Biến thể 2 là một truy vấn trực tiếp do đó nó nhanh hơn.

1

Truy vấn đầu tiên có truy vấn phụ nặng. Bạn phải tránh điều này. Giải pháp tốt nhất cho vấn đề của bạn chỉ là một truy vấn:

SELECT name FROM mytable GROUP BY personal_number HAVING COUNT(*) > 1; 

Truy vấn này sẽ trả lại cho bạn mỗi tên lặp lại chỉ một lần. Nếu bạn muốn hiển thị tên của trùng lặp nhiều lần như họ gặp nhau bạn phải sử dụng truy vấn tiếp theo:

SELECT name, COUNT(*) AS count FROM mytable GROUP BY personal_number HAVING COUNT(*) > 1; 

Và sau đó trong PHP làm điều gì đó như thế này:

foreach ($rows as $row) { 
    for ($i = 0; $i++; $i < $row['count']) { 
    echo $row['name'] . "\n"; 
    } 
} 
Các vấn đề liên quan