« 1 2 »
Autor Zpráva
siginigin
Profil *
zdravim, urobil som select, problem vsak je, ze strasne dlho trva, je to nepouzitelne :(
select * from tab1 left join tab2 on tab1.id = tab2.id 
where tab1.pole1 like "%text%" or tab1.pole2 like "%text%" or ... tab1.pole10 like "%text%" or 
      tab2.pole1 like "%text%" or tab2.pole2 like "%text"% or ... tab2.pole80 like "%text%"

z tohto by mala vzniknut tabulka, v ktorej budu vsetky zaznamy z tab1, k nim sa doplnia zaznamy z tab2 a nasledne podla kriterii where sa vyberu pozadovane zaznamy.

v tab1 je 65536 zaznamov, id je primarny kluc a index zaroven, obsahuje 10 poli
v tab2 je asi 2000 zaznamov, id je index, obsahuje 80 poli
db mysql 5.0.67-community-nt
vznikne mi teda obrovsky select, zatial ho mam hotovy len 1/3 a uz teraz trva 75 sekund. a takychto selectov potrebujem urobit 36.

co mam zmenit aby to chodilo rychlejsie? vdaka
xmark
Profil
Špatně navržená databáze.
Můžeš popsat, o co se jedná?

Docela mě zaujalo těch 65536 řádků.
__construct
Profil
xmark:
Špatně navržená databáze.
Prikláňam sa.

siginigin:
Podľa toho dotazu to vyzerá, že chceš robiť vyhľadávanie - na to ale slúži fulltext
siginigin
Profil *
v tab1 je zoznam ip adries napr.172.17.0.0/16 = 65536 adries, tab2 je doplnujuce info k tymto ip, ak je na nejakej ip pc, tak pozbierane data sa ulozia do tab2. tab1 je jedna z 36 tabuliek, 2 su o velkosti 65536, ostatne 256.
no pravdepodobne budu zle indexy, tak prave skumam explain, ale docital som sa ze velke spomalenie moze sposobovat ten join...
siginigin
Profil *
__construct:
hmm fulltext? to bude asi ono!
__construct
Profil
siginigin:
velke spomalenie moze sposobovat ten join
Nie je pravda .. to veľké spomalenie pravdepodobne spočíva v tom že vyhľadávaš za použitia tzv. wildcard na začiatku fráze v (prepokladám) 90 stĺpcoch ..

Ako ukladáš IP adresy? Odporúčam ako INT UNSIGNED a na vkladanie/vyberanie INET_ATON/INET_NTOA
xmark
Profil
siginigin:
A proč pro porovnávání s "172.17.0.0/16" používáš like? Když ten porovnávaný string zredukuješ přesně do toho tvaru, můžeš použít rovnítko, nebo ne?

Jinak - adresy bych určitě skladoval jako pět TINYINTů.
To, že tabulek jako tab1 je 36 a tab2 má 80 polí .. nevím. Může to mít opodstatnění. Ale jestli máš v moci jak to ukládání, tak čtení dat, organizoval bych to jinak.
xmark
Profil
__construct:
(Za INET_ATON dík, neznal jsem)
siginigin
Profil *
Teraz ukladám adresy ako varchar(15). V čom je výhoda, ak ich budem ukladať ako čísla?

Upravujem štruktúru tab2, každé pole nech je fulltext, len neviem, či mám dať fulltext na každé pole osobitne, alebo na všetky naraz. Je to zjavne rozdiel...
alter table tab2 add fulltext (pole1)
alter table tab2 add fulltext add (pole2, pole3)
no a písali, že výsledky sa zoraďujú podľa relevancie, ale ja ich chcem zoradiť podľa IP adresy, mám teda použiť:
select * from tab1 left join tab2 on tab1.id = tab2.id 
where match (všetky polia s fulltextom) against ("text") 
order by tab1.ip

?
__construct
Profil
siginigin:
V čom je výhoda, ak ich budem ukladať ako čísla?
Menej to bude zaberať a tým pádom aj vyhľadávanie bude rýchlejšie ;-)

Na ten fulltext používaj radšej boolean mode

Inak stále nechápem čo presne chceš a mám taký dojem, ako sme spomínali na začiatku že by sa to dalo riešiť efektívnejšie zmenou designu databáze a tým pádom by nebolo treba ten fulltext
siginigin
Profil *
Tak je to tak, že v 36 tabuľkách sú siete (id, ip, hostname, posledná odozva, stav) a v tej jednej sú informácie pozbierané cez WMI, je ich približne 80. Skener prechádza sieť a ak nájde PC, pozbiera z neho dáta a uloží. Záznamy môžu obsahovať viacero položiek v jednom poli, napr. PC má dva disky, tak v jednom poli bude uložené "Disk1@Disk2". K tomu mám ešte jednu tabuľku, ktorá obsahuje zoznam sietí, názvy a id-čka, lebo tabuľky sietí sa volajú subnet_<id>. Lepšie som to vtedy nevedel vymyslieť :S.
Nuž a výsledok celého tohto je, aby user mal jedno políčko, keď bude niečo hľadať a tento jeho text sa vyhľadá vo všetkých poliach. A samozrejme musí to byť svižné. To je vše, čo od toho očakávam. :)
__construct
Profil
siginigin:
Podľa toho čo čítam, by si si mal najprv preštudovať niečo o normalizácii
Mastodont
Profil
Záznamy môžu obsahovať viacero položiek v jednom poli, napr. PC má dva disky, tak v jednom poli bude uložené "Disk1@Disk2"
To je v drtivé většina případů průser. Pak už se totiž nedá vyhledávat pomocí "=", ale musíš použít LIKE a rychlost dotazů je příšerná. Opravdu si prostuduj tu normalizaci.
siginigin
Profil *
No ale to by som musel vyrobiť 80 nových tabuliek a na vybratie jedného záznamu buď joinovať všetky tieto tabuľky, alebo vytvoriť 80 selectov. To sa mi tiež nezdá veľmi efektívne.
Mastodont
Profil
Mně nepřipadá efektivní dotaz trvající 75 sekund ... a hledání jedné hodnoty ve více sloupcích, viz tvoje

where tab1.pole1 like "%text%" or tab1.pole2 like "%text%" or ... tab1.pole10 like "%text%"

je prostě gigantický kiks.
ninja
Profil
siginigin:
No ale to by som musel vyrobiť 80 nových tabuliek a na vybratie jedného záznamu buď joinovať všetky tieto tabuľky, alebo vytvoriť 80 selectov. To sa mi tiež nezdá veľmi efektívne.


Nemusel. Je možné mít atributivní tabulku se strukturou typy: pc_id, attr_type, attr_value
siginigin
Profil *
Mastodont:
plne s tebou súhlasím, že súčasná verzia je nepoužiteľne pomalá. len vzhľadom na to, že je to kopec písania a klikania sa bojím, že select z 80 joinovaných tabuliek bude ešte pomalší a nakoniec výsledok nebude stáť za to úsilie.
len sa teda chcem uistiť či je toto (80 nových tabuliek) správna cesta...
__construct
Profil
siginigin:
To sa mi tiež nezdá veľmi efektívne
Určite ten dotaz nezaberie viac ako zlomok sekundy
Okrem toho môžeš urobiť to čo napísal ninja tabuľku s atribútmi a v nej vytvoríš dvojicu primárnych kľúčov - id počítača a názov/typ atribútu.
siginigin
Profil *
siginigin, __construct:
ninja:
no ale to vôbec nie je zlý nápad :) skúsim to tak urobiť, attr_value teda nastaviť ako fulltext predpokladám...
takto by mohol vyzerať select?:
select * from tab1 left join attr_table on tab1.ip = attr_table.ip 
where match (attr_value) against ('+text' in boolean mode) order by ip 
__construct
Profil
Teraz ma napadlo, že ak by si potreboval tých tabuliek 80 tak JOINom by to nešlo - MySQL vie max. 60
Mastodont
Profil
siginigin:
Já rozhodně netvrdím, že 80 tabulek je lepších. Můj dojem je ten, že prostě neumíš navrhovat tabulky a že by jich stačilo třeba jen 5 - bylo by nejlepší, kdybys sem dal celou strukturu (nejlépe jako odkaz na nějaký obrázek). Jinak ti moc neporadíme.
__construct
Profil
siginigin:
Prikláňam sa k Mastodontovi - hoď sem model DB; stále mám dojem, že niečo robíš zle, pretože FULLTEXT primárne slúži na niečo iné..
<mimo-téma>
len tak som skúsil vybrať dáta z jednej testovacej tabulky (cca 300k riadkov) 60krát som ju JOINol samu na seba a vyberal som jeden riadok - správne použité INDEXy a LIMIT = dotaz zabral 0,016 sekundy
</mimo-téma>
siginigin
Profil *
no ako som spomínal vyššie:
jedna tabulka je siete (id , nazov, rozsah, maska) - v nej sú adresy sietí. potom mám 36 tabuliek nazvaných subnet_<id z tabuľky siete>, čiže subnet_1 až subnet_36 (id, ip, hostname, posledna odozva, stav) - tu by možno bolo lepšie mať jednu veľkú tabuľku so všetkými adresami (keď som s týmto začínal, pripadalo mi prehľadnejšie mať to takto roztriedené). no a potom jedna tabuľka (id, ip, 80 polí z WMI), s tabuľkami subnet_<id> je previazaná cez ip.

tak skúsim to takto:
jedna tabulka je siete (id , nazov, rozsah, maska)
jedna tabulka je ip (id , id_siete, ip, hostname, posledna odozva, stav)
siete inner join ip on siete.id = ip.id_siete
a jedna tabuľka info (id, ip, premenna, hodnota)
ip inner join info on ip.ip = info.ip

čo vy na to?
nightfish
Profil
siginigin:
čo vy na to?
rozhodně lepší než původní řešení
__construct
Profil
siginigin:
a jedna tabuľka info (id, ip, premenna, hodnota)
ip inner join info on ip.ip = info.ip
Nepotrebuješ mať v tabuľke info IP adresu - ukladaj tam radšej id.id - bude pravdepodobne menší a rýchlejší
siginigin
Profil *
__construct:
jasne, už som zmenil

a ešte jedna otázka: predtým som všetkých 80 polí uložil jedným insertom, teraz budem musieť urobiť 80 insertov. Alebo je nejaký krajší spôsob?
Mastodont
Profil
No jestli to je do stejných sloupců, tak existuje syntaxe
INSERT INTO tbl_name (a,b,c) VALUES(1,2,3),(4,5,6),(7,8,9);
siginigin
Profil *
no paráda, tak mám všetko, už len to nakódiť ;)

veľká vďaka všetkým vám za pomoc.
siginigin
Profil *
zdravím, tak som to urobil, ako sme sa predtým bavili, ale čas selectu je 13 sekund, to je stále veľa.
prikladám screenshoty: 1. select, 2. explain, 3. tabuľka subnet, 4. tabuľka ip, 5. tabuľka ip_info

phpmyadmin

ten "like" je v selecte kvôli tomu, že keď user zadá iba časť adresy, tak očakáva, že sa mu zobrazia všetky, ktoré tak začínajú.

v tabuľke subnet je 36 záznamov, v tabuľke ip je ~140 000 záznamov a v tabuľke ip_info je ~11 000 000 záznamov - pokusne som do nej nasypal toľko, aby každá adresa z tabuľky ip mala všetkých 80 polí (140 000 x 80).

vďaka za radu.
__construct
Profil
To zlo tam robí kombinácia LIKE a INET_NTOA - robí sa to pre každý riadok zvlášť (treba vymyslieť iné riešenie)
//edit: Pozri si ako sa vypočítava adresa. Možno Ťa napadne lepšie riešenie (mňa už napadlo :-))
« 1 2 »

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:

0