2008-12-09 43 views
50

Tôi có 2 bảng (A và B) với cùng một khóa chính. Tôi muốn chọn tất cả hàng đó là A và không có trong B. Các công trình sau đây:Mysql chọn nơi không có trong bảng

select * from A where not exists (select * from B where A.pk=B.pk); 

tuy nhiên nó có vẻ khá xấu (~ 2 giây trên chỉ 100k hàng trong A và 3-10k ít hơn trong B)

Có cách nào tốt hơn để thực hiện việc này không? Có lẽ như là một tham gia trái?

select * from A left join B on A.x=B.y where B.y is null; 

Dữ liệu của tôi dường như chạy nhanh hơn một chút (~ 10%) nhưng nói chung thì sao?

+0

Bạn có nghĩa là bạn có 100 nghìn hàng trong bảng A và 100 nghìn hàng trong bảng B không? Hoặc chỉ khoảng 300 hàng trong mỗi bảng, có nghĩa là quét hàng 100.000 (hoặc, hy vọng, quét chỉ mục). – ChrisInEdmonton

Trả lời

35

Tôi sử dụng truy vấn ở định dạng ví dụ thứ hai của bạn. Tham gia thường có khả năng mở rộng hơn so với truy vấn con tương quan.

50

Tôi nghĩ câu cuối cùng của bạn là cách tốt nhất. Bạn cũng có thể thử

SELECT A.*  
from A left join B on 
    A.x = B.y 
    where B.y is null 
+1

Điều đó không có ý nghĩa gì cả. Khi B.y là null, A.x = B.y sẽ không bao giờ đúng. Bạn sẽ nhận được tất cả các hàng của A, không chỉ các hàng không có hàng phù hợp trong B. –

+2

@Bill nhưng nó hoạt động! Thêm vào đó là chính xác điều tương tự như tuyên bố thứ hai được liệt kê ở trên. –

+2

Tôi đã thay đổi và ở đâu. – hamstar

2

Tôi cũng sử dụng các kết nối trái với tiêu chí loại "where table2.id is null".

Chắc chắn có vẻ hiệu quả hơn tùy chọn truy vấn lồng nhau.

2

Tham gia thường nhanh hơn (trong MySQL), nhưng bạn cũng nên xem xét lược đồ lập chỉ mục của mình nếu bạn thấy rằng nó vẫn đang di chuyển chậm. Nói chung, bất kỳ thiết lập trường nào là khóa ngoài (sử dụng INNODB) sẽ có một bộ chỉ mục. Nếu bạn đang sử dụng MYISAM, hãy đảm bảo rằng bất kỳ cột nào trong câu lệnh ON được lập chỉ mục và cũng xem xét thêm bất kỳ cột nào trong mệnh đề WHERE vào cuối chỉ mục, để làm cho nó trở thành một chỉ mục bao trùm. Điều này cho phép động cơ có quyền truy cập vào tất cả các dữ liệu cần thiết trong chỉ mục, loại bỏ sự cần thiết phải thực hiện một chuyến đi khứ hồi thứ hai trở lại dữ liệu gốc. Hãy nhớ rằng điều này sẽ ảnh hưởng đến tốc độ chèn/cập nhật/xóa, nhưng có thể làm tăng đáng kể tốc độ truy vấn.

+0

Thực ra, Raul, bản chỉnh sửa của bạn làm cho âm thanh giống như bạn nên tạo một chỉ mục riêng cho các cột trong mệnh đề WHERE.Để rõ ràng, tôi có nghĩa là để thêm các cột vào chỉ số (bao gồm chỉ mục), do đó, động cơ sẽ không phải thực hiện một chuyến đi khứ hồi trở lại dữ liệu cơ sở cho mệnh đề WHERE. Xin lỗi vì không rõ ràng. – Chosun

-2

Điều này đã giúp tôi rất nhiều. Joins luôn nhanh hơn Truy vấn phụ để cung cấp kết quả:

SELECT tbl1.id FROM tbl1 t1 
LEFT OUTER JOIN tbl2 t2 ON t1.id = t2.id 
WHERE t1.id>=100 AND t2.id IS NULL ; 
Các vấn đề liên quan