2010-04-13 4 views
7
$s = explode (" ", microtime()); 
$s = $s[0]+$s[1]; 
$con = mysqli_connect ('localhost', 'test', 'pass', 'db') or die('Err'); 

for ($i=0; $i<1000; $i++) { 

    $stmt = $con -> prepare(" SELECT MAX(id) AS max_id , MIN(id) AS min_id FROM tb "); 
    $stmt -> execute(); 
    $stmt->bind_result($M,$m); 
    $stmt->free_result(); 
    $rand = mt_rand($m , $M).'<br/>'; 

    $res = $con -> prepare(" SELECT * FROM tb WHERE id >= ? LIMIT 0,1 "); 
    $res -> bind_param("s", $rand); 
    $res -> execute(); 
    $res->free_result(); 
} 

$e = explode (" ", microtime()); 
$e = $e[0]+$e[1]; 
echo number_format($e-$s, 4, '.', ''); 

// and: 

$link = mysql_connect ("localhost", "test", "pass") or die(); 
mysql_select_db ("db") or die ("Unable to select database".mysql_error()); 

for ($i=0; $i<1000; $i++) { 
    $range_result = mysql_query(" SELECT MAX(`id`) AS max_id , MIN(`id`) AS min_id FROM tb "); 
    $range_row = mysql_fetch_object($range_result); 
    $random = mt_rand($range_row->min_id , $range_row->max_id); 
    $result = mysql_query(" SELECT * FROM tb WHERE id >= $random LIMIT 0,1 "); 
} 

chuẩn bị phát biểu defenitly được nhiều hơn nữa an toàn hơn nhưng cũng mỗi nơi nó nói rằng họ là nhanh hơn nhiều NHƯNG trong thử nghiệm của tôi trên các mã trên tôi có: - 2,45 giây cho chuẩn bị phát biểu - 5,05 giây cho Secon ví dụCác câu lệnh chuẩn bị không nên nhanh hơn nhiều?

Bạn nghĩ mình đang làm gì sai? Tôi có nên sử dụng giải pháp thứ hai hay tôi nên cố gắng tối ưu hóa tiêu chuẩn chuẩn bị?

+6

2,45 * nhanh hơn 5,05? –

+2

vui lòng định dạng mã để có thể đọc được. –

+0

OMG .. mọi người có thể không hiểu gì nếu bạn viết như thế này .. định dạng nó đúng cách. –

Trả lời

23

Điều bạn đang làm sai là bạn đang chuẩn bị báo cáo hàng nghìn lần và chỉ chạy từng câu lệnh đã chuẩn bị một lần. Bạn nên chuẩn bị nó một lần, và chạy nó hàng ngàn lần.

+2

Để rõ ràng hơn, bạn nên chuẩn bị nó một lần, và sau đó ràng buộc và thực hiện nó một nghìn lần. – MJB

+1

Đó là điều xảy ra khi mọi người không hiểu khái niệm bất biến trong vòng lặp: -/ –

+0

Tôi đặt cả hai câu lệnh chuẩn bị vào vòng lặp và bây giờ tôi có aprox 2,39 giây và trong sol.2 tôi có 2,45. Có bình thường không? Nó chỉ là một cải tiến 3%. – silversky

4

Không có lợi ích gì khi chuẩn bị một câu lệnh bên trong một vòng lặp cho một lần thực thi duy nhất. Bạn chỉ cần thêm phí. Sử dụng câu lệnh đã chuẩn bị cho các truy vấn bạn thực hiện thường xuyên với các tham số khác nhau.

+0

có thực sự đó là một sai lầm lớn để đặt chuẩn bị stmt bên trong vòng lặp nhưng sau khi tôi đặt cả hai chuẩn bị otside vòng lặp kết quả là 2.39sec mà chỉ Tốc độ tăng 3% Không nên nhiều hơn? – silversky

+1

không nhất thiết. Tiết kiệm chính là từ việc soạn một kế hoạch truy vấn cho truy vấn. Nếu đó là một câu lệnh SQL tầm thường, không có gì nhiều để tiết kiệm. Không có gì thực sự được biên dịch nên thực sự không có bất kỳ chu kỳ CPU nào để nói, và nếu truy vấn của bạn đang truy cập vào ổ đĩa (tức là dữ liệu không được lưu trữ) sẽ nhanh chóng giảm bớt bất kỳ khoản tiết kiệm chu kỳ nào - việc truy cập đĩa chậm hơn nhiều hơn chu kỳ CPU. – dkretz

+0

db không phải là lớn nó chỉ có 42.000, nhưng tôi đã hy vọng tiết kiệm nhiều hơn nữa. Nhưng có lẽ bạn đã wright. – silversky

1

Ngoài các câu trả lời ở trên ...

Tôi thấy bạn đang sử dụng MySQL và dưới đây là liên kết từ đó như để chuẩn bị phát biểu: http://dev.mysql.com/tech-resources/articles/4.1/prepared-statements.html

Một đoạn trích từ đó:

Sự gia tăng hiệu suất trong các báo cáo chuẩn bị có thể đến từ một vài tính năng khác nhau. Đầu tiên là cần phải phân tích cú pháp truy vấn một lần duy nhất. Khi ban đầu bạn chuẩn bị câu lệnh, MySQL sẽ phân tích cú pháp câu lệnh để kiểm tra cú pháp và thiết lập truy vấn để chạy. Sau đó, nếu bạn thực hiện truy vấn nhiều lần, nó sẽ không còn có phí trên đó nữa. pre-phân tích này có thể dẫn đến một sự gia tăng tốc độ nếu bạn cần phải chạy cùng một truy vấn nhiều lần

+1

Như tôi đã nói, tôi biết đó là một sai lầm lớn khi đặt chúng vào vòng lặp, nhưng sau khi tôi đặt $ con -> preparation() bên ngoài tôi chỉ nhận được 3-5% tốc độ tăng. tôi đã được mong đợi nhiều hơn, ít nhất 20-30% tốc độ gia tăng. – silversky

+0

Tại sao bạn mong đợi một phần trăm tùy ý tăng tốc? Hiệu suất đạt được và đo lường của họ không hoạt động theo cách đó. Điều đó hoàn toàn phụ thuộc vào kích thước dữ liệu bạn đang tìm nạp và thông lượng (xem phản hồi của tôi để được giải thích rõ hơn). –

+0

Để thêm vào đó, tôi nghĩ bạn nên kỳ vọng vào việc sử dụng các câu lệnh đã chuẩn bị về lâu dài và sức khỏe của ứng dụng của bạn dưới dạng các đối tượng tạm thời được tạo trong quá trình phân tích cú pháp. Không phải trên số thực thi thô. Và vì nó hiếm khi được biết khi nào và cách truy vấn (hoặc bất kỳ đoạn mã nào) sẽ được sử dụng theo thời gian, cách tốt nhất là làm cho tất cả các câu lệnh được chuẩn bị. –

2

@silversy -

Vòng cơ bản 101 (hoặc đồng bằng mã hóa 101): Di chuyển loop-bất biến mã ra khỏi các vòng . Tại sao bạn chuẩn bị câu lệnh trong vòng lặp khi không có tham số nào phụ thuộc vào vòng lặp?

Tất nhiên nó sẽ hút tuyến sinh dục nếu bạn sử dụng câu lệnh đã chuẩn bị nếu bạn chuẩn bị chúng với mỗi vòng lặp lặp lại. Các chi phí bạn quan sát là trong tuyên bố ban đầu được chuẩn bị hơn là trong thực hiện của nó.

lại làm mã của bạn như sau, và lại thử lại:

$stmt = $con -> prepare(" SELECT MAX(id) AS max_id , MIN(id) AS min_id FROM tb "); 
$res = $con -> prepare(" SELECT * FROM tb WHERE id >= ? LIMIT 0,1 "); 

for ($i=0; $i<1000; $i++) { 

    $stmt -> execute(); 
    $stmt->bind_result($M,$m); 
    $stmt->free_result(); 
    $rand = mt_rand($m , $M).'<br/>'; 

    $res -> bind_param("s", $rand); 
    $res -> execute(); 
    $res->free_result(); 
} 


Thông báo trước đây, mặc dù, đó là sự khác biệt giữa một tuyên bố chuẩn bị và một không chuẩn bị trở nên không đáng kể như thời gian tính toán để thực hiện truy vấn và tìm nạp dữ liệu trở nên lớn.

Chỉ cần kéo một số con số hư cấu ra khỏi @@@ của tôi vì lợi ích của minh họa:

Nói rằng các truy vấn bản thân và quá trình tìm nạp dữ liệu mất 0.01sec (gọi A này). Ngoài ra, hãy tưởng tượng rằng việc xây dựng và thực thi mã đằng sau câu lệnh đã chuẩn bị mất 0,01 giây (X) và cho truy vấn chưa chuẩn bị 0,05 giây hoặc 5 * 0,01 giây (Y = 5 * X).Các suất ăn giữa mã chuẩn bị và chuẩn bị sẽ là:

(A + Y)/(A + X) = 0.06sec/0.02sec = 3 -> unprepared execution is three times slower 

Và chúng ta hãy giả sử rằng cho truy vấn khác, thời gian quyến rũ (do khối lượng dữ liệu hoặc thông mạng) là 10secs (1000 * 0.01sec). Sau đó, tỷ lệ thay đổi

(A + Y)/(A + X) = 10.05sec/10.01sec ~=~ 1.004 

Chúng không thể phân biệt được. Những gì tôi đang cố gắng nói là có, các câu lệnh chuẩn bị nhanh hơn (và bạn nên sử dụng chúng), NHƯNG thử nghiệm bạn đang thực hiện không nhất thiết phải là cách tốt để tìm ra hoặc đánh giá giá trị của chúng. Bạn phải tính đến các yếu tố khác để thực sự đo lường hiệu suất bạn đang ép ra khỏi chúng.

+0

@ uis.espinal, cảm ơn bạn rất nhiều – silversky