2010-03-31 45 views
6

đó là hiệu quả hơn (khi quản lý hơn 100K hồ sơ):MySQL vs PHP khi lấy một mục ngẫu nhiên

A. Mysql

SELECT * FROM user ORDER BY RAND(); 

tất nhiên, sau đó tôi sẽ đã có tất cả các các trường từ bản ghi đó.

B. PHP

sử dụng memcached để có $ cache_array giữ tất cả các dữ liệu từ "SELECT id_user TỪ sử dụng ORDER BY id_user" trong vòng 1 giờ hoặc lâu hơn ... và sau đó:

$ id = array_rand ($ cache_array);

tất nhiên, sau đó tôi phải thực hiện một cuộc gọi MYSQL với:

SELECT * FROM user WHERE id_user = $id; 

như vậy ... đó là hiệu quả hơn? A hoặc B?

+0

trùng lặp: http://stackoverflow.com/questions/1823306/alerternative-to-mysql-order-by-rand –

+2

@OMG Ngựa Non: Đó là tương tự, nhưng không phải là một người bị mắc mưu.Anh ấy không yêu cầu cách tốt nhất để thực hiện nó trong Mysql, anh ấy yêu cầu so sánh hai phương pháp. – ryeguy

+0

Theo đồ thị này (xem liên kết ở cuối), ~ 100K được sắp xếp theo RAND() là phụ thứ hai. Tôi tò mò muốn xem liệu PHP (ít hơn .NET hay J2EE) sẽ cung cấp hiệu suất tương tự: http://stuff.dasprids.de/images/benchmark-random-row-full.png –

Trả lời

8

Cách thích hợp để trả lời loại câu hỏi này là làm điểm chuẩn. Thực hiện triển khai nhanh chóng và dơ bẩn theo từng cách và sau đó chạy thử nghiệm điểm chuẩn để xác định xem thử nghiệm nào hoạt động tốt hơn.

Có nói rằng, ORDER BY RAND() được biết là chậm vì không thể để MySQL sử dụng chỉ mục. Về cơ bản, MySQL sẽ chạy hàm RAND() một lần cho mỗi hàng trong bảng và sau đó sắp xếp các hàng dựa trên những gì đã trở về từ RAND().

Ý tưởng khác của bạn lưu trữ tất cả user_id s trong memcached và sau đó chọn một yếu tố ngẫu nhiên hình thức mảng có thể thực hiện tốt hơn nếu chi phí của memcached chứng minh là ít hơn chi phí của một bảng đầy đủ quét. Nếu tập dữ liệu của bạn lớn hoặc không ổn định, bạn có thể gặp sự cố. Ngoài ra, bạn đang thêm một số phức tạp vào ứng dụng của mình. Tôi sẽ cố gắng tìm cách khác.

Tôi sẽ cung cấp cho bạn tùy chọn thứ ba có thể hoạt động tốt hơn cả hai đề xuất của bạn: Chọn count(user_id) trong số các hàng trong bảng người dùng của bạn và sau đó có php tạo số ngẫu nhiên từ 0 đến kết quả của count(user_id) trừ 1. Sau đó, hãy thực hiện SELECT * FROM user LIMIT 1 OFFSET random-number-generated-by-php;.

Một lần nữa, cách thích hợp để trả lời các loại câu hỏi này là điểm chuẩn. Bất cứ điều gì khác là đầu cơ.

+0

+1 cho tùy chọn thứ ba –

+0

điều này sẽ làm việc tuyệt vời, ngoại trừ việc tôi quên xác định rằng các bản ghi có thể được chọn phải được lọc bằng WHERE flg_pic = 1. Nếu tôi làm một số (id_user) các hồ sơ có flg_pic = 0 cũng sẽ được xem xét: s – andufo

+0

@ andufo: Đây không thực sự là một vấn đề gì cả. Bạn có thể thực hiện 'SELECT COUNT (user_id) FROM user WHERE flg_pic = 1;' và sau đó 'SELECT * FROM user WHERE flg_pic = 1 LIMIT 1 OFFSET ngẫu nhiên-số-tạo-bởi-php;'. – Asaph

4

Người đầu tiên là cực kỳ chậm vì

MySQL tạo ra một bảng tạm thời với tất cả các hàng quả và gán cho mỗi một trong số họ một chỉ số thứ tự ngẫu nhiên. Kết quả sau đó được sắp xếp và được trả lại.

Nó được chi tiết hơn trên this blog post.

0
$random_no = mt_rand(0, $total_record_count); 

$query = "SELECT * FROM user ORDER BY __KEY__ LIMIT {$random_no}, 1"; 
Các vấn đề liên quan