我使用PHP 5.3.6與PDO來訪問Postgres 9.0.4。我被要求減少報告的內存佔用量。當前的實現很簡單:執行查詢,執行fetchAll(),然後通過結果數組遍歷foreach()。這顯然不會隨着巨大的結果集擴展:它可以暫時消耗100MB或更多。迭代Postgres/PHP/PDO中結果集的最佳實踐?
我有一個新的實現,它採用PDO語句句柄,然後使用foreach()直接迭代它,即通過fetchAll()沒有中間數組。 (從我讀過的內容中,迭代一個語句句柄,並在foreach中調用fetch())。這同樣快,並且消耗的方式是更少的內存:大約28kB。不過,我不相信我這樣做是正確的,因爲雖然我已經做了谷歌搜索噸的,這是很難找到答案這個基本問題:
我見過的文章,建議用遊標解決我原來的問題。 Postgress PDO驅動程序是否已經在內部使用遊標?如果需要編寫自己的SQL來創建遊標,我願意,但我寧願寫最簡單的代碼(但不是簡單的!)。
如果foreach調用fetch()每次迭代,是不是太網絡健談?或者它很聰明並且一次取多行,例如500,節省帶寬? (這可能意味着它在內部使用光標。)
我見過一篇文章,將語句句柄包裝在實現Iterator接口的類中。鑑於PDO語句句柄已經做到這一點,這不是多餘的嗎?或者我錯過了什麼?
我的電話準備SQL語句如下:
而$ sth = $ dbh->準備($的SQL);
我發現,它並沒有內存或速度的區別,如果我這樣做:
$sth = $dbh->prepare($sql, array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY));
這是因爲這是默認反正Postgres的PDO驅動程序?如果它已經在內部使用光標,這將是有意義的。
歡迎提供有關解決此問題的方法和其他方法的一般意見。
謝謝,喬恩。確實如此 - 我沒有想過要直視源頭。我讀到它說,沒有智能一次提取多於一行,並緩衝它們在客戶端以減少網絡流量。除非發生在Postgres客戶端的更深層次,否則驅動程序會調用它,但似乎不太可能。我會做一些性能測試,看看我的簡單實現如何在不同的盒子上與客戶端和Postgres一起工作。如果它太慢,我會推出自己的。 – DaveBurns
FWIW,我認爲驅動程序源代碼是它沒有使用prepare()的可選參數。希望聽到有人不同意。 – DaveBurns