引用:
FIEND:
如果 我的 db 有 一千萬筆資料
我全部都要入 變數 再 count ...
應該會 error ....
1. count 陣列變數太誇張了..
我在 db
而且 findall 我己經下 limit 了說
塞入 變數 的想法 真的很酷 不敢用會被打死 .
你不了解查詢結果的記憶體管理機制。
當 PHP 向 DB 查詢資料後,資料內容就已經被儲存在 PHP 這方的記憶體內容了。說的更明白些:
$resource = mysql_query($query);
此時 $resource 已經是一個儲存了查詢結果的變數(但型態不是陣列)。如果查詢結果有一千萬筆資料,那麼 $resultSet 就會配置那麼多的記憶體空間儲存那一千萬筆資料。接著再使用 mysql_fetch_array() 等方法取出個別資料記錄。
RTM:
引用:
PHP Manual::mysql_query
The returned result resource should be passed to mysql_fetch_array(), and other functions for dealing with result tables, to access the returned data.
----
PHP Manual::mysql_free_result
mysql_free_result() will free all memory associated with the result identifier result.
mysql_free_result() only needs to be called if you are concerned about how much memory is being used for queries that return large result sets.
那被查詢出的一千萬筆資料並不是保存在 DB 端。
有碼有真相,來一段測試過程。首先查詢一個上萬筆的記錄結果,然後 sleep() 暫停 PHP 程式執行。再以 top(Unix) 或 工作管理員(windows) 觀看 PHP 程式查詢前後使用的記憶體變化量,就知道查詢的資料結果是被儲存在哪了。
<?php
$link = mysql_connect('localhost', 'mysql_user', 'mysql_password');
$query = 'SELECT * FROM my_table'; //有幾萬筆資料的查詢結果
$resource = mysql_query($query, $link);
sleep(120); //暫停2分鐘
mysql_free_result($resource);
sleep(120);
?>
你說把一千萬筆資料"塞入變數"會被打死,那你連 findAll() 都不能用,因為會被打死。你只能每次都向 DB 查詢"剛好一筆"資料。但我相信,這樣做絕對死更快。
ps. PHP 口中的 resource 其實就是一個"塞入很多內容的變數"。
引用:
FIEND:
mysql_result 的 method 並沒有在 db_souces 下被運用.
一般情況下 , 我會利用 mysql_result 去取 出我要的 第 n 筆的 record .
然後用 while 告訴它我只要取幾筆..
而在沒有 conettion close 之前.
我就可以用 mysql_num_rows 去取得它的個數.
而我也沒有用 limit 去 下 query .
所以我可以 要出 我要的二種資料.
mysql 的function 並不是只有 fetch_array ....
為什麼一定要用 limit 去達成 page 效果
而 model 和 db_souces 又沒有提供 result 的用法
如此 即為 為什麼我覺得 cake在換頁的表現有待加強.
一個經驗老道的 PHP programmer ,會定義一個 SPL::ArrayObject 的衍生類別,將 resource 及存取函數都封裝進去。
$resource = mysql_query($query);
class ResultSet extends ArrayObject {
protected $resource;
public function __construct($resource) {
$this->resource = $resource;
}
public function count() {
return mysql_num_rows($this->resource);
}
public function offsetGet($index) {
return mysql_result($this->resource, $index);
}
}
$dbResultSet = new ResultSet($resource);
echo count($dbResultSet);
$record = mysql_result($resource, 0);
$record = $dbResultSet[0];
如此一來,用 count() 取得資料結果筆數有何問題?
啥,CakePHP 沒用 ArrayObject ,而是直接把 resource 的記錄內容轉成 array ?那也沒什麼不好啊,直接用陣列運算子就能操作資料了,比 mysql_xxx() 更簡單。所以你抱怨 "mysql_result 的 method 並沒有在 db_souces 下被運用",這毫無意義。
再說到 limit 的問題,這實際上就是記憶體管理的問題,也就是我在本文第一段回應的內容,但由於你不清楚這方面的機制,所以我再強調一次,在換頁功能中使用 limit 是為了節省記憶體。
最後,我要修正一下我前篇回應的錯誤。我前篇回應了忽略了 findAll() 有 limit n 的敘述在內,所以用 count() 得到的數目必定小於等於 n ,而不是結果總筆數。因為一次 交易只能回傳一個結果。就此而言,先用 findAll() 再用 findCount() 是不得已的舉措。
就算我在一次交易中塞入2行查詢敘述,一個查內容(limit n),一個查 count ,但 DB 只會回傳最後一行查詢敘述的結果,第一行敘述的結果則不會回傳。
不過老練的 SQL 人員會一招 UNION 指令,可以把2個查詢敘述併成一行,使得2個查詢結果合併為一個,就可以傳回來了。