Autor Zpráva
raddimm.xx
Profil
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
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
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 *
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
Tam, kde bude první null hodnota, začnete vytvářet uzly (první bude mít rodiče podle předešlého nalezeného, další podle nově vytvořeného).


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
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.

Vaše odpověď

Mohlo by se hodit


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm: