2012-04-01 31 views
8

Tôi có vẻ hơi khó khăn. Đó là một truy vấn khá thẳng thắn.Trợ giúp Mysql cần thiết để tối ưu hóa nhóm theo truy vấn phụ

Nếu tôi chạy các truy vấn riêng biệt, nó không phải là chậm nhưng khi tôi kết hợp chúng rất chậm.

Tôi không chắc chắn cách tối ưu hóa nó. Bất kì sự trợ giúp nào đều được đánh giá cao. Về cơ bản, tôi chỉ muốn hiển thị nhiều khoản tiền hoàn lại. Vì vậy, nơi faultid tồn tại nhiều lần.

SELECT 
    r.* 
FROM 
    faultrefunds_v2 r 
WHERE 
    r.id IN (SELECT r1.id 
      FROM faultrefunds_v2 r1 
      GROUP BY faultid 
      HAVING count(r1.faultid) > 1); 

Kết quả từ giải thích được đã được đính kèm một hình ảnh

enter image description here

+0

Là r.id primar y key? –

+0

có và lỗi là khóa ngoài –

+0

Tôi nghĩ truy vấn bạn đã viết không trả lời được câu hỏi. Điều này là do một khi bạn đã nhóm theo lỗi, bạn sẽ chỉ trả lại một r.id cho lỗi đó. –

Trả lời

1

Tôi đoán, điều này đủ điều kiện chứ không phải như một viết lại hơn như tối ưu hóa, nhưng đây là những gì tôi sẽ thử thay vào đó, anyway:

SELECT 
    r.* 
FROM faultrefunds_v2 r 
WHERE EXISTS (
    SELECT * 
    FROM faultrefunds_v2 r1 
    WHERE r1.faultid = r.faultid 
    AND r1.id <> r.id 
); 
+0

điều này cũng làm việc. –

+0

tại sao điều này nhanh hơn nhiều so với truy vấn tôi đã viết? họ trông khá giống nhau? –

+1

Truy vấn của bạn sử dụng nhóm, là một hoạt động tương đối đắt tiền, để bắt đầu. Hơn nữa, truy vấn phụ thuộc loại đó được cho là quét toàn bộ bảng để xây dựng hàng được đặt để khớp với. Truy vấn của tôi, mặt khác, sử dụng một semi-join (trong dạng của 'EXISTS' predicate). Trong bán kết nối, các kết quả phù hợp cho một hàng dừng được tìm kiếm ngay khi tìm thấy ít nhất một hàng, bạn có thể đoán có thể tăng tốc truy vấn một cách đáng kể trong trường hợp có nhiều kết quả phù hợp cho một số/hầu hết các hàng. –

1

Tôi nghĩ rằng câu hỏi của bạn không trả lời câu hỏi. Theo tôi hiểu nó, trước tiên bạn nên nhận được tất cả các lỗi có nhiều hơn một id liên quan (hàng trong bảng). Và sau đó nhận được tất cả các hàng đó (không chỉ là errorId).

Hãy thử điều này:

select * from faultrefunds_v2 
where faultId in (
    select faultId from faultrefunds_v2 
    group by faultId 
    having count(*) > 1 
) 
+0

Tôi nghĩ rằng đây là một cải tiến về truy vấn của tôi, nó hợp lý hơn và giải thích hơn. Nhưng nó vẫn còn khá chậm. cho nó +1 –

2

IN khoản theo cách bạn sử dụng nó sẽ rất chậm, sử dụng JOIN thay vì:

SELECT r.* FROM ( 
    SELECT r1.id AS id 
    FROM faultrefunds_v2 r1 
    GROUP BY faultid 
    HAVING count(r1.faultid) > 1 
) AS ids 
LEFT JOIN faultrefunds_v2 AS r 
ON(ids.id = r.id) 
+0

công trình này, nó rất nhanh. Bạn có thể giải thích tại sao mệnh đề IN chậm với cách tôi sử dụng nó để tôi có thể tránh làm điều đó một lần nữa không? –

+1

MySql thường không lập chỉ mục các phần tử bên trong mệnh đề IN nên nó nên so sánh id của mỗi hàng trong bảng 'r' với tất cả các id được tìm thấy trong truy vấn con mỗi lần. Trong phương pháp MySql tìm tất cả các id thích hợp một lần sau đó lấy hàng đầy đủ cho mỗi id trong truy vấn bên ngoài rất nhanh chóng bằng cách sử dụng chỉ mục. – nobody

+0

Câu trả lời này là câu trả lời đúng bên cạnh câu trả lời của Andiry M. Tôi không thể chấp nhận hai câu trả lời (mặc dù tôi nghĩ rằng nó có thể có hai câu trả lời đúng nhưng khác nhau cho cùng một câu hỏi). –

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