Komentáře k článku
Ukládáme hierarchická data v databázi – III

V minulých dvou dílech jsme si ukázali rozdíl mezi „klasickou“ cestou ukládání stromu a představili jsme si metodu MPTT. Předtím, než se zběsile vrhneme do implementace v rámci našich CMS, podívejte se, na jaké problémy jsme během tří let narazili my.
mazání v MPTT stromu
Dobrý den,
nebylo by lepší využít k mazání spíše delete pracující pomocí left a right ala:
mysql_query(„DELETE FROM strom WHERE lft >= $row[lft] AND rgt <= $row[rgt]“); ?
viz http://php.vrana.cz/traverzovani-kolem-stromu-prakticky.php
Nemuselo by se pak volat mazání každé položky podstromu zvlášť, ale obstaral by to jeden sql query.
Re: mazání v MPTT stromu
No tady jde asi o to, ze ke kazde polozce ve stromu potrebuju smazat taky polozku z jine tabulky, tak asi proto.
Re: mazání v MPTT stromu
A kde je problém?
1) delete …. where polozka_id in (select polozka_id from ….between … and …)
2) delete from strom where strom_id between … and …
Re: mazání v MPTT stromu
Nebo ještě lépe: cizí klíče a kaskáda.
Re: mazání v MPTT stromu
Autorovo řešení mazání ve foreach cyklu mi přijde zbytečně neoptimální.
Pokud se nepletu, pro každého potomka ( $descendants ) v uvedeném příkladu zasílán jednu query na DELETE (viz: dibi::query(„DELETE FROM [mptt] WHERE [id] = %i“, $one[‚id‘]); ), což při počtu např. 1000 potomků znamená 1001 dotazů na db.
Tudíž se mi zdá lepší výše uvedené řešení (to v prvním příspěvku), které používá 1 query na DELETE ať už mažeme jakýkoli počet potomků.
Současně díky cizím klíčům a cascade delete jsou mazány i referencující položky v jiných tabulkách.
Z trochu jiného soudku, netuší někdo, jak napsat query tak, aby posunula UZEL stromu (vč. jeho podstromu) níže ve stejné úrovni?
Tzn. prohodit jej s následujícím uzlem (pokud má následníka).
Znamená to přepočítat left a right obou těch uzlů, zatím se mi však nepodařilo najít ten správný algoritmus, fungují mi pouze posuny uzlů směrem vzhůru ( na stejné úrovni).
Re: mazání v MPTT stromu
My to řešili obecným přesunem ve stromu. Tzn. že dovedeme přesunout jakýkoliv uzel kamkoliv. Z hlediska prohození dvou uzlů na stejné úrovni to není nejoptimálnější řešení, ale funguje to dobře. K většímu rozdílu ve výkonu mezi nejoptimálnější a naší verzi dojde pokud vpravo od přesouvaných položek je hodně uzlů.
Pokud by jste chtěl modifikovat pouze lft/rgt přesouvaných uzlů a jejich potomků, musel by jste řešit problém chvilkové duplicity lft/rgt přesouvaných stromů a nebo dočasně jeden strom přesouvaného uzlu odklidit mimo aktuální rozsah (např. použít záporná čísla).
Vymyslet to by asi nebyl problém, ale u nás to byla jen podmnožina celkového problému přesunu uzlů. Stejně jsme potřebovali řešit obecné přesuny, takže jsme vyřešili přesuny a optimalizaci nechali na příště ;-). Výkonostní problémy máme nyní jinde (např přidávání uzlu do stromu pokud má strom 100k položek).
knihovna
Nakonec pro Vás mám lahůdku – vytvořil jsem vám knihovnu pro práci s MPTT…. já ji tam prostě nevidím :)
Re: knihovna
Toto je lepsie:
http://www.sideralis.org/baobab/index.html
Flattened tree navigation
alter table TREE add column NodePath VARCHAR(1024)
insert into TREE (NodeId, NodeName, NodePath) values(newId, newName, parentPath + sprintf(‚%5d“,newId))
create index ix_node_path on TREE(NodePath)
…
pak všechny uzly pod daným uzlem:
select * from TREE where NodePath LIKE ‚xxxxx%‘
Omezení – hloubka stromu, počet položek, storage
Výhody – performance boost, jak čtení tak zápis je rychlý (žádný traversal), jednoduché hromadné operace
MS SQL 2008 R2+ umí T-TREE indexy, umí opravdu překvapivě rychle i
select * from TREE where NodePath LIKE ‚%xxxxxyyyyy%‘
tedy operace se subtrees