Doctrine, kdy idealne fushovat

kleinpetr
Člen | 480
+
0
-

Zdravim,

mel bych takovy dotaz, prave testuji import xml a ulozeni do databaze, jde o to, ze jsem myslel, ze bude nejlepsi (rychlejsi) projit data, persistnout a az na zaver celeho importu to odpalit pres flush()

Jenze po spusteni mi na vps jede php na 100% coz asi neni ok, tak me napadla otazka, jedna se o tisice zaznamu, ktere se drzi v persistenci pred flushnutim. Neni to ten problem ? ze je ten objekt prilis velky a tudiz php umira ? Nebude lepsi flushovat treba po kazdem zaznamu nebo sekvenci zaznamu ?

Diky za info, rad bych to nejak zoptimalizoval :)

kleinpetr
Člen | 480
+
0
-

Tak jina otazka, zjistil jsem, ze je mnohem rychlejsi pouzivat transakce, mel jsem totiz problem v tom, ze jsem volal flush u jinych zaznamu, ale ty logicky odpalili vse co bylo do te doby persistnute.

Nicmene mam 2 otazky

  1. kdyz zavolam $em->persist($entity) – flushne to opravdu pouze tu jednu entitu ?
  • protoze nacitam nekolik tisic zaznamu do transakce a kompletni flush() mam az na konci skriptu, ale behem skriptu mam nejake flushovani prave pouze nejakych entit, ale pri projizdeni to uklada po nahodnych skupinach, nekdy po 1000 nebo po 2000 nekdy po 300, tak si rikam, proc se tomu tak deje ?
  1. prochazim v jednom skriptu nekolik xml souboru a vsiml jsem si, ze si zrejme php neco uklada do pameti, tak si rikam, neni potreba nejak vycistit ten entityManager, nebo se vycisti pri kazdem flush() ? Zkusil jsem dat vzdy na konec nacteni jednoho feedu $em->clear() ale to pak dopadlo spatne, protoze se vymazali vsechny nactene entity. Nebo co by se mohlo uchovavat v pameti v prubehu prochazeni ?

Diky

Matey
Člen | 142
+
0
-
  1. áno, ak nemáš v danej entite cascade persist na inú entitu
  2. s tým čistením takto http://docs.doctrine-project.org/…cessing.html
kleinpetr
Člen | 480
+
0
-

@Matey Diky, a jak je to s tim, ze po ruznych castich se provadi flush ? Je to standartni chovani ?

Pro predstavu dam priklad

prochazim produkty (napr. 50 000)
pri pruchodu vytvorim ProductEntity a pokusim se najit kategorii v databazi, pokud ji nenajdu, tak vytvorim novou CategoryEntity → flushnu ji a priradim ji k nactene ProductEntity, takovych veci, je tam vice, ale nikde nevolam flush() ani flush($ProductEntity) a presto se produkty zapisuji dodatabaze po ruznych skupinach, jak jsem psal, nekdy po 1000 nekdy po 2000 atd.

Matey
Člen | 142
+
0
-

asi to bude tým že dôjde pamäť a keďže do toho náhodne vytváraš a načítavaš iné entity tak sa veľkosť tých skupín mení. Ale nikde som to nevyčítal a nemám s tým ani skúsenosti. Najjednoduchšie asi skúsiť zmeniť memory limit a hneď uvidíš či je to tým.

Alebo proste použiť to čo doctrine dokumentácia odporúča a flushovat po menších častiach.

kleinpetr
Člen | 480
+
0
-

@Matey jaky memory_limit mas na mysli ? na vps mam jeste dost volne pameti, a skript poustim pres cli, kde je memory_limit –1

Kazdopadne, to flushovani po davkach by mi asi ani tak nevadilo, ale problem jse ze muj kod vypada asi nasledovne (zjednodusene)

foreach ($providers as $providerEntity)
{
	foreach ($providerEntity->getFeeds() as $feedEntity)
	{
		//$xml = parse xml data from url
		foreach ($xml->products as $product)
		{

			$categoryEntity = $categoryRepository->findByName($product->category);
			if(!$categoryEntity){
				$categoryEntity = new CategoryEntity();
				$em->persist($categoryEntity);
				$em->flush($categoryEntity);
			}

			$productEntity = new ProductEntity();
			$productEntity->setCategory($categoryEntity);

			$em->persist($productEntity);
		}

		$em->flush();

		//kdyz clear() na tomto miste, tak se mi vymazali i nacetle entity
		//takze mi to pri dalsim pruchodu hodilo chybu s ProviderEntity
		//resp. tu ProviderEntity pak nekde ukladam, a chyba byla ohledne toho, ze byla nalezena nova enetita
		//ale na asociaci neni nastaveno cascade persist, takze si proste jakoby zahodila ta reference...
	}
}

btw, prisel jsem na to, ze kdyz prochazim nejaky feed, ktery obsahuje kategorie, ktere jeste nejsou v db, tak se produkty vkladaj po 2–3 zaznamech.. asi je opravdu flushne manager i presto, ze jsem jako parametr uvedl pouze $categoryEntity..

Editoval kleinpetr (3. 3. 2018 9:31)

Matey
Člen | 142
+
0
-
$batchSize = 20;
foreach $providers as $providerEntity
{
	foreach $providerEntity->getFeeds() as $feedEntity
	{
		$xml = parse xml data from url
		$i = 1;
		foreach $xml as $product
		{
			$productEntity = new ProductEntity();
			//...
			$em->persist($productEntity);

			if (($i % $batchSize) === 0) {
				$em->flush();
				$em->clear(ProductEntity::class);
			}
			$i++;
		}
		$em->flush();
		$em->clear(ProductEntity::class);
	}
}

v dokumentácii sa spomína že sa dajú čistiť entity podľa mena, takže by mohlo pomôcť niečo takéto

Editoval Matey (3. 3. 2018 9:48)

kleinpetr
Člen | 480
+
0
-

@Matey jojo, to me taky napadlo, zkusim mazat ProductEntity::class a dam vedet, jak to dopadlo :) Diky