Autor | Zpráva | ||
---|---|---|---|
raddimm.xx Profil |
#1 · Zasláno: 2. 3. 2016, 11:21:22
Mám stromovou strukturu ktera obsahu 3 miliony radku
struktura db tabulky id, parentid, name, level pri cteni vsechno jaks taks funguje. Nyní potřebuji udělat update = přidat cca 500 000 řádku. Problém je, že v csv mám novou cestu a potřebuji první porovnat jestli existuje a pak přidat pokud neexistuje. Je to strašně pomalé, šíleně zabírá diskové operace atd. Nějaké rady? Postupuji tak, že mám novou cestu například "jidelnicek-zdrave jidlo-ryby-smazene"; rozparusji a porovnovan existuje v level 1 jidelnicek, atd atd |
||
Kajman Profil |
#2 · Zasláno: 2. 3. 2016, 11:25:38
Jakou databázi používáte?
|
||
raddimm.xx Profil |
Kajman:
mysql / MyISAM ještě přidal jsem dva sloupce akce1 a akce2 (tinyint) porovnavam odle nich uricte statusy jen přečíst data: SELECT * FROM xxx WHERE akce3 = '99' AND akce1!='8' LIMIT 1 trvá 15 vteřin |
||
Keeehi Profil |
#4 · Zasláno: 2. 3. 2016, 13:02:00
raddimm.xx:
1) mít sloupce indexované čísly většinou ukazuje na špatný návrh „jen přečíst data: SELECT * FROM xxx WHERE akce3 = '99' AND akce1!='8' LIMIT 1 trvá 15 vteřin“ 2) jak jsou na tom indexy? |
||
anonymníí Profil * |
#5 · Zasláno: 2. 3. 2016, 13:03:36
raddimm.xx:
Ještě doplním Keeehiho: 3) sloupce jsou číselné, vyhoď ty apostrofy kolem číselných hodnot. Zbytečně tam musí docházet k přetypování, které zdržuje (ne v řádu sekund, ale i tak). |
||
Kajman Profil |
raddimm.xx:
Mysql nepodporuje hiearchické dotazy. Občas se na ní používá traverzování kolem stromu, které dokáže pomoci s dotazy nad stromy díky dopočítaným pomocným sloupcům. V současném stavu bych zkusil 1. zredukovat csv tak, aby tam byly jen koncové uzly (např. pokud budou dva řádky "jidelnicek-zdrave jidlo-ryby-smazene" a "jidelnicek-zdrave jidlo-ryby", tak "jidelnicek-zdrave jidlo-ryby" vyhodit). To by po seřazení nemělo být algoritmicky složité. 2. při kontrole, zda tam uzel je, zjistit jedním dotazem, kde končí shoda. Tedy podle délky zanoření generovat dotaz s více sloupci a více joiny, něco jako select t1.id id_1, t2.id id_2, t3.id id_3, t4.id id_4 from dual left join tabulka t1 on t1.name='jidelnicek' and t1.level=1 and t1.parentid is null left join tabulka t2 on t2.name='zdrave jidlo' and t2.level=2 and t2.parentid=t1.id left join tabulka t3 on t3.name='ryby' and t3.level=3 and t3.parentid=t2.id left join tabulka t4 on t4.name='smazene' and t4.level=4 and t4.parentid=t3.id Stále to bude pomalé, ale snad to trošku stroji ulehčí. Nevím, co tam máte za indexy, ale na dotaz v kroku 2, by se hodil třeba dvouslopcový (name, parentid). Edit: a při větším zanoření než 60, je potřeba udělat více dotazů, to už by bylo na limit počtu joinů v mysql dotaze. |
||
Kajman Profil |
#7 · Zasláno: 2. 3. 2016, 16:30:57
Další variantou by bylo naimportovat (nejlépe load from file) soubor csv (musí to být kompletní strom bez redukce) do pomocné tabulky se sloupci
fullDir dir previousDir level 'jidelnicek-zdrave jidlo-ryby-smazene' 'smazene' 'jidelnicek-zdrave jidlo-ryby' 4 'jidelnicek-zdrave jidlo-ryby' 'ryby' 'jidelnicek-zdrave jidlo' 3 'jidelnicek-zdrave jidlo' 'zdrave jidlo' 'jidelnicek' 2 'jidelnicek' 'jidelnicek' null 1 Udělat nad tabulkou indexy: (level, dir), fullDir, previousDir - poslední dva asi typu hash.
A pak postupně dělat inserty podle levelu 1..max(level) ze spojení cílové tabulky s dočasnou. insert into tabulka (parentid, name, level) select null, d.dir, d.level from docasna_tabulka d left join tabulka t on t.name=d.dir and t.level=d.level and t.parentid is null where d.level=1 and t.level is null insert into tabulka (parentid, name, level) select t1.id, d2.dir, d2.level from docasna_tabulka d2 join docasna_tabulka d1 on d1.fullDir=d2.previousDir and d1.level=1 join tabulka t1 on t1.name=d1.dir nad t1.level=d1.level left join tabulka t2 on t2.name=d2.dir and t2.level=d2.level and t2.parentid=t1.id where d2.level=2 and t2.level is null . . . Takže do cílové tabulky budete mít tolik insertů, kolik je maximální level nového stromu. A na limit na počet tabulek ve spojení narazíte už při hloubce 30. |
||
Časová prodleva: 9 let
|
0