Postgres - gruplar halinde bir sorgu çalıştırmak?

4 Cevap php

(Örneğin) 500.000 satır bulunursa, bu ilk 10.000 sonuçlarını döndürmek ve tekrar sorguyu yeniden çalıştırın edeceğiz böylece bir sorgu döngü mümkün mü?

Peki, ne yapmak istediğinizi bir sorgu çalıştırmak ve bu gibi bir dizi inşa edilir:

$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++;
}

Ama birkaç yüz bin satır olacağını biliyorum, bu yüzden gibi 10,000 ... 1 gruplar halinde bunu yapmak istedim - 9999 ve daha sonra 10.000 - Ben bu hatayı almaya devam çünkü vs .. 10.999 nedeni budur:

Fatal error: Allowed memory size of 536870912 bytes exhausted (tried to allocate 3 bytes)

Tesadüfen, ben 3 bayt 512M tüketebileceği nasıl anlamıyorum ... Yani ben sadece değiştirebileceğiniz bir şey olursa yine gruplar halinde bunu yapmak için daha iyi olabilir, ancak, bu harika olurdu?

4 Cevap

Sen LIMIT (x) ve OFFSET (y) kullanabilirsiniz

Bu son 3 byte devenin belini kıran saman vardı. Yetmezliğine yol tahsisler uzun bir dizesinde Muhtemelen bir ayırma girişimi.

Ne yazık ki libpq uygulamaya kontrol vazgeçmiş önce fully cache result sets in memory çalışacağız. Bu $myArray kadar kullandığınız her türlü bellek ek olarak.

Bu LIMIT ... OFFSET ... to reduce the memory envelope; this will work, but is inefficient o could gereksiz sırayla örneğin (ofset sunucu tarafı sıralama çabayı sorgu farklı bir ile reissued her zaman çoğaltmak olarak kullanmak için öne sürülmüştür sadece satır 10000 .. 10010 dönmek için LIMIT 10 OFFSET 10000 Postgrees hala tüm sonuç kümesini sıralamak zorunda olacak cevap.)

Bunun yerine, DECLARE ... CURSOR to create a server-side cursor, FETCH FORWARD x to fetch the next x satır takip kullanın. Az-daha-x satır döndürülür kadar gerektiği gibi birçok kez tekrarlayın ya. İşiniz bittiğinde, CLOSE imleç unutmayın bile / bir istisna yükseldi eğer.

Ayrıca, do not SELECT * ; if you only need id ve name, imleci oluşturmak FOR SELECT id, name (aksi libpq gereksiz alır ve önbellek sütun Eğer bellek ayak izi ve genel sorgu zaman artan, asla kullanmayın.)

Yukarıda gösterildiği gibi imleci kullanarak, libpq herhangi bir anda bellekte x satırlar en tutacaktır. Ancak, aynı zamanda FETCH es mümkünse yoksa hala $myArray hesabına bellek tükendi olabilir arasında senin $myArray temizlemek emin olun.

Aslında ne olursa olsun bir bellek tüketilmesine neden olacak böyle bir döngü içinde diziye ekleyerek, böylece onları almak kadar PostgreSQL sunucusu önbelleklerini Sonuçları sorgusu. Bir seferde sonuçlar bir satır işlemek, ya da sonuç şimdiye kadar çekti, ve sonra dizi temizlemek dizi, sürecin uzunluğunu kontrol Ya.

Ne hata demektir PHP 3 bayt ayırmaya çalışıyor, ancak 512MB tüm mevcut kısmının az 3 bayt olmasıdır.

Eğer toplu olarak yapmak bile, sonuçta elde edilen dizinin boyutuna bağlı hala kullanılabilir belleği tüketebileceği.

Belki de gerçekten tüm kayıtları almak gerekmez?