Postgres - 批量运行查询?

Caf*_*eIV 5 php memory postgresql loops

是否可以循环查询以便如果(例如)找到500,000行,它将返回前10,000个的结果,然后再次重新运行查询?

所以,我想要做的是运行查询并构建一个数组,如下所示:

$result = pg_query("SELECT * FROM myTable");

$i = 0;
while($row = pg_fetch_array($result) ) {
  $myArray[$i]['id'] = $row['id'];
  $myArray[$i]['name'] = $row['name'];
  $i++;
}
Run Code Online (Sandbox Code Playgroud)

但是,我知道会有几十万行,所以我想分批完成10,000个等级... 1- 9,999然后10,000 - 10,999等...原因是因为我一直收到这个错误:

Fatal error: Allowed memory size of 536870912 bytes exhausted (tried to allocate 3 bytes)
Run Code Online (Sandbox Code Playgroud)

顺便说一句,顺便说一句,我不明白3个字节如何耗尽512M ...所以,如果那是我可以改变的东西,那就太好了,尽管如此,批量做这个仍然可能更好?

vla*_*adr 6

最后3个字节是打破骆驼背部的稻草.可能是在长串分配中导致失败的分配尝试.

不幸的是,在将控制权交给应用程序之前,libpq将尝试在内存中完全缓存结果集.这是你正在使用的任何内存的补充$myArray.

有人建议使用它LIMIT ... OFFSET ...来减少内存包络; 这将起作用,但效率低下,因为每次使用不同的偏移重新发出查询时,它可能会不必要地复制服务器端排序工作(例如,为了回答LIMIT 10 OFFSET 10000,Postgres仍然必须对整个结果集进行排序,仅返回行10000 ..10010.)

相反,用于DECLARE ... CURSOR创建服务器端游标,然后FETCH FORWARD x获取下一x行.根据需要重复多次,或直到x返回少于行.完成后不要忘记CLOSE光标,即使/如果异常上升.

另外,不要SELECT * ; 如果你只需要idname,创建你的光标FOR SELECT id, name(否则libpq将不必要地检索和缓存你从未使用的列,增加内存占用和整体查询时间.)

使用如上所示的游标,任何时候libpq都将x在内存中保留最多行.但是,如果可能的话,请确保您也在es $myArray之间进行清理,FETCH否则您的内存仍会因内存不足而导致内存不足$myArray.


小智 5

您可以使用LIMIT (x)OFFSET (y)