2010-03-23 31 views
11

Tôi biết rằng Tất cả bộ nhớ kết quả được liên kết sẽ tự động được giải phóng khi kết thúc quá trình thực thi tập lệnh. Nhưng bạn có khuyên bạn nên sử dụng nó, nếu tôi đang sử dụng khá nhiều hành động tương tự như dưới đây?

$sql = "select * from products"; 
$result = mysql_query($sql); 
if($result && mysql_num_rows($result) > 0) { 
    while($data = mysql_fetch_assoc($result)) { 
    $sql2 = "insert into another_table set product_id = '".$data['product_id']."' 
       , product_name = '".$data['product_name']."' 
      "; 
    $result2 = mysql_query($sql2); 
    **mysql_free_result($result2);** 
    } 
} 

Cảm ơn.

+3

Tôi chân thành hy vọng mã bạn trích dẫn chỉ để minh họa - tất cả điều này có thể được thực hiện trong một truy vấn SQL: INSERT INTO another_table (product_id, product_name) SELECT product_id, product_name FROM product – symcbean

Trả lời

18

Trích dẫn tài liệu của mysql_free_result:

mysql_free_result() chỉ cần được gọi nếu bạn lo lắng về cách dung lượng bộ nhớ đang được sử dụng cho các truy vấn trả lại tập kết quả lớn.
Tất cả bộ nhớ kết quả được liên kết là được tự động giải phóng ở cuối thực thi của tập lệnh .


Vì vậy, nếu các tài liệu nói nó thường không cần thiết phải gọi hàm đó, tôi sẽ nói đó là không thực sự cần thiết, và cũng không thực hành tốt, gọi nó ;-)

Và, chỉ để nói : Tôi gần như không bao giờ gọi hàm đó; bộ nhớ được giải phóng ở cuối tập lệnh và mỗi tập lệnh không được ăn quá nhiều bộ nhớ.
Một ngoại lệ có thể là các lô dài chạy phải xử lý một lượng lớn dữ liệu, mặc dù ...

1

Tùy thuộc vào truy vấn của bạn lớn hay số truy vấn bạn chạy. PHP tự động giải phóng bộ nhớ ở cuối tập lệnh, nhưng không phải trong khi chạy. Vì vậy, nếu bạn có một lượng lớn dữ liệu đến từ một truy vấn, tốt hơn miễn phí kết quả theo cách thủ công.

tôi sẽ nói: YES, một thói quen tốt vì bạn quan tâm đến bộ nhớ trong sự phát triển hoặc kịch bản của bạn và đó là những gì làm cho một nhà phát triển tốt :-)

+0

Tin tưởng tôi khi tôi nói rằng "mysql_free_result () "các cuộc gọi của riêng họ không nhất thiết là một chỉ báo tốt của một nhà phát triển tốt. – Kzqai

4

Vâng, đó là thực hành tốt để sử dụng mysql_free_result($result). Tài liệu được trích dẫn trong câu trả lời được chấp nhận là không chính xác. Đó là những gì tài liệu nói, nhưng điều đó không có ý nghĩa gì cả. Dưới đây là những gì nó says:

mysql_free_result() chỉ cần được gọi nếu bạn lo ngại về số lượng bộ nhớ đang được sử dụng cho các truy vấn trả lại tập kết quả lớn. Tất cả bộ nhớ kết quả được liên kết sẽ tự động được giải phóng ở cuối quá trình thực thi của tập lệnh.

Phần đầu tiên của câu đầu tiên là chính xác. Đúng là bạn không cần sử dụng nó vì những lý do khác với những lo ngại về bộ nhớ. Lo ngại về bộ nhớ là lý do duy nhất để sử dụng nó. Tuy nhiên, phần thứ hai của câu đầu tiên không có ý nghĩa gì cả. Yêu cầu bồi thường là bạn sẽ chỉ quan tâm đến bộ nhớ cho các truy vấn trả lại các tập kết quả lớn. Điều này là rất gây hiểu nhầm vì có những trường hợp phổ biến khác mà bộ nhớ là một mối quan tâm và gọi mysql_free_result() là thực hành rất tốt. Mọi truy vấn thời gian có thể chạy một số lần không xác định, càng nhiều bộ nhớ sẽ được sử dụng hết nếu bạn không gọi mysql_free_result(). Vì vậy, nếu bạn chạy truy vấn của bạn trong một vòng lặp, hoặc từ một chức năng hoặc phương pháp, nó thường là một ý tưởng tốt để gọi mysql_free_result(). Bạn chỉ cần cẩn thận để không giải phóng kết quả cho đến khi nó không còn được sử dụng nữa.Bạn có thể tự bảo vệ mình khỏi phải suy nghĩ về thời gian và cách sử dụng nó bằng cách tạo các hàm select() và ex() của riêng bạn để bạn không làm việc trực tiếp với các tập kết quả. (Không có mã nào ở đây chính xác là cách tôi thực sự viết nó, nó minh họa hơn. Bạn có thể muốn đặt chúng trong một lớp hoặc vùng tên đặc biệt và ném một loại Ngoại lệ khác hoặc tham số bổ sung như $class_name, v.v. .)

// call this for select queries that do not modify anything 
function select($sql) { 
    $array= array(); 
    $rs= query($sql); 
    while($o= mysql_fetch_object($rs)) 
     $array[]= $o; 
    mysql_free_result($rs); 
    return $array; 
} 

// call this for queries that modify data 
function ex($sql) { 
    query($sql); 
    return mysql_affected_rows(); 
} 

function query($sql) { 
    $rs= mysql_query($sql); 
    if($rs === false) { 
     throw new Exception("MySQL query error - SQL: \"$sql\" - Error Number: " 
      .mysql_errno()." - Error Message: ".mysql_error()); 
    } 
    return $rs; 
} 

Bây giờ nếu bạn chỉ gọi select()ex(), bạn chỉ là đối phó với biến đối tượng bình thường và chỉ có mối quan tâm bộ nhớ bình thường thay vì quản lý bộ nhớ bằng tay. Bạn vẫn phải suy nghĩ về những lo ngại về bộ nhớ bình thường như bao nhiêu bộ nhớ đang được sử dụng bởi một mảng các đối tượng. Sau khi biến nằm ngoài phạm vi, hoặc bạn tự đặt nó thành null, nó trở nên có sẵn để thu thập rác để PHP xử lý điều đó cho bạn. Bạn có thể vẫn muốn đặt nó thành null trước khi nó hết phạm vi nếu mã của bạn không sử dụng nó nữa và có các thao tác theo sau nó sử dụng một lượng bộ nhớ không xác định như vòng lặp và các cuộc gọi hàm khác. Tôi không biết các bộ kết quả và các hàm hoạt động trên chúng được thực hiện như thế nào (và ngay cả khi tôi đã làm, điều này có thể thay đổi với các phiên bản PHP và MySQL tương lai khác), vì vậy có khả năng hàm select() xấp xỉ gấp đôi số lượng bộ nhớ được sử dụng ngay trước khi mysql_free_result($rs) được gọi. Tuy nhiên bằng cách sử dụng select() vẫn loại bỏ những gì chúng ta thường là mối quan tâm chính của ngày càng nhiều bộ nhớ được sử dụng trong vòng lặp và các cuộc gọi chức năng khác nhau. Nếu bạn lo lắng về khả năng sử dụng bộ nhớ đôi này và bạn chỉ làm việc với một hàng tại một thời điểm trong một lần lặp, bạn có thể tạo một hàm() sẽ không tăng gấp đôi mức sử dụng bộ nhớ của bạn và sẽ bảo vệ bạn khỏi suy nghĩ về mysql_free_result():

each($sql,$fun) { 
    $rs= query($sql); 
    while($o= mysql_fetch_object($rs)) 
     $fun($o); 
    mysql_free_result($rs); 
} 

bạn có thể sử dụng nó như thế này:

each("SELECT * FROM users", function($user) { 
    echo $user->username."<BR>"; 
}); 

Một lợi thế của việc sử dụng mỗi() là nó không trả lại bất cứ điều gì, vì vậy bạn không cần phải suy nghĩ về việc liệu hoặc không đặt giá trị trả về thành null sau này.

0

Câu trả lời dĩ nhiên là CÓ trong mysqli.
Hãy xem PHP mysqli_free_result documentation:

Bạn nên luôn luôn giải phóng kết quả của bạn với mysqli_free_result(), khi đối tượng kết quả của bạn là không cần thiết nữa.

tôi sử dụng để thử nghiệm nó với chức năng memory_get_usage:

echo '<br>before mysqli free result: '.memory_get_usage(); 
mysqli_free_result($query[1]); 
echo '<br>after mysqli free result'.memory_get_usage(); 

Và nó là kết quả:

before mysqli free result:2110088 
after mysqli free result:1958744 

Và ở đây, chúng ta đang nói về 151,344 bytes bộ nhớ trong chỉ 1000 hàng bảng mysql. Làm thế nào về một triệu hàng và làm thế nào để suy nghĩ về các dự án lớn?
mysqli_free_result() không chỉ cho số lượng lớn dữ liệu, nó cũng là một thực hành tốt cho các dự án nhỏ.

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