Forum » Programiranje » SQL inner join
SQL inner join
Jure14 ::
Imam dve veliki tabeli in eno težavo.
Uporabljam MySQL (ker nima omejitve v velikosti baze v free varianti).
Imam 2 tabeli, precej veliki.
V prvi je cca 100.000.000 zapisov.
V drugi cca 20.000.000 zapisov.
Pa še več jih bo v obeh.
Rad pa bi dobil seznam ključev, ki so v obeh tabelah.
Torej presek obeh tabel.
select * from a , b where a.id = b.id
ali pa
select * from a join b on a.id = b.id
In oboje traja celo večnost.
Oz. sploh ne dobim rezultata, ker workbench javi napako: 2013 Lost connection to MySQL server during query
A se da še na kak drug način dobit presek?
Uporabljam MySQL (ker nima omejitve v velikosti baze v free varianti).
Imam 2 tabeli, precej veliki.
V prvi je cca 100.000.000 zapisov.
V drugi cca 20.000.000 zapisov.
Pa še več jih bo v obeh.
Rad pa bi dobil seznam ključev, ki so v obeh tabelah.
Torej presek obeh tabel.
select * from a , b where a.id = b.id
ali pa
select * from a join b on a.id = b.id
In oboje traja celo večnost.
Oz. sploh ne dobim rezultata, ker workbench javi napako: 2013 Lost connection to MySQL server during query
A se da še na kak drug način dobit presek?
klemenSLO ::
Kolk je pa polj? včasih zna pomagat že to da namesto select * navedeš samo eno polje - v tvojem primeru a.id.
Life is not measured in minutes, but in MOMENTS...
Jure14 ::
V večji tabeli sta 2 polji, v manjši samo ID.
Index je na obeh primarni na ID.
Obe tabeli sta na MyISAM, ker ne rabim zaklepanja, pa logov, pa podobnih zadev.
Index je na obeh primarni na ID.
Obe tabeli sta na MyISAM, ker ne rabim zaklepanja, pa logov, pa podobnih zadev.
steev ::
Probal pri sebi, sicer postgres, v dveh velikih tabelah (25 in 15 milijonv) pa je vzelo 25 sekund.
:|
Utk ::
Ce ves katera tabela je manjsa, bi jaz poskusil z select * from manjsa where id in (select iz vecje). Ker tako in tako mora it cez celo tabelo. Najprej se pa vprasaj ce res to rabis.
WarpedGone ::
Zelo bo pomagalo če namesto * selektiraš samo polja ki so v indeksu i.e. polje ID, enkrat.
Tako zadeva sploh ne bo dostopala do tabel ampak samo do obeh indeksev.
Ker nimaš nobene dodatne omejitve bo delal full index scan kar pomeni da bo prebral cel index. Splača se query obrnit tako, da bo prebral cel manjši index in njegove ključe iskal po večjemu. In ne obratno.
Predvidevam, da je polje ID v obeh tabelah navadna številka, kar pomeni da mora prebrat nekaj sto megabajtov, kar tut za čistonavaden HDD ni noben problem in bi moralo bit fertig v roku nekaj minut.
Če se ti vmes seveda ne vpleta nekaj čisto tretjega.
Tako zadeva sploh ne bo dostopala do tabel ampak samo do obeh indeksev.
Ker nimaš nobene dodatne omejitve bo delal full index scan kar pomeni da bo prebral cel index. Splača se query obrnit tako, da bo prebral cel manjši index in njegove ključe iskal po večjemu. In ne obratno.
Predvidevam, da je polje ID v obeh tabelah navadna številka, kar pomeni da mora prebrat nekaj sto megabajtov, kar tut za čistonavaden HDD ni noben problem in bi moralo bit fertig v roku nekaj minut.
Če se ti vmes seveda ne vpleta nekaj čisto tretjega.
Zbogom in hvala za vse ribe
Jure14 ::
> Poraba pomnilnika
WorkBench + sql server skupaj cca 4GB
> Tip polja ID
znakovni, 45 znakov.
WorkBench + sql server skupaj cca 4GB
> Tip polja ID
znakovni, 45 znakov.
BRBR ::
Ponavad se pred sql da EXPLAIN,
in pol ti bo pisalo using temporary, če bo. Tudi ti to pove če ima morda namen uporabit kake indexe.
temporary - ti bo kvačkalo vmesne
rezultate po disku in bo mlelo in mlelo.
Da se npr. mu dopovedat da naj namesto diska za temporary uporablja ram ...., če ga maš. Boljši je sicer SSD.
Še ena komand je ki se je zdajle ne spomnim ki ti pove kolk sec. ti porabi za posamezno operacijo querya : statistcs, sending data, ...
tko iz glave, se mi zdi da ti index na a tako ali tako nič ne pomaga, probaj EXPLAIN
in pol ti bo pisalo using temporary, če bo. Tudi ti to pove če ima morda namen uporabit kake indexe.
temporary - ti bo kvačkalo vmesne
rezultate po disku in bo mlelo in mlelo.
Da se npr. mu dopovedat da naj namesto diska za temporary uporablja ram ...., če ga maš. Boljši je sicer SSD.
Še ena komand je ki se je zdajle ne spomnim ki ti pove kolk sec. ti porabi za posamezno operacijo querya : statistcs, sending data, ...
select * from a join b on a.id = b.id
tko iz glave, se mi zdi da ti index na a tako ali tako nič ne pomaga, probaj EXPLAIN
Zgodovina sprememb…
- spremenil: BRBR ()
kuall ::
execution plan in gledaš index scan (bad).
kaj hitrejšga kot join na indexe ne boš našel.
primary key naj bo številka, če hočeš, da bodo joini karseda hitri.
kaj hitrejšga kot join na indexe ne boš našel.
primary key naj bo številka, če hočeš, da bodo joini karseda hitri.
Jure14 ::
WarpedGone je izjavil:
znakovni, 45 znakov.
Tle se začne tvoj problem.
Ampak drugače ne gre.
Ker podatke dobim v CSV datoteki, za obe tabeli.
In potem bulk insert, pa obdelava (join).
steev ::
WarpedGone je izjavil:
znakovni, 45 znakov.
Tle se začne tvoj problem.
Ampak drugače ne gre.
Ker podatke dobim v CSV datoteki, za obe tabeli.
In potem bulk insert, pa obdelava (join).
Pa maš primer idja? Je integer ali ne?
:|
Apple ::
Napisal je, da je ID znakovni, 45 znakov.
A maš to enkratno akcijo, al ponavljajočo?
A maš to enkratno akcijo, al ponavljajočo?
LP, Apple
Jure14 ::
Ideja je, da bi se dnevno uvažalo iz CSVjev in delal presek.
Pomožna ideja je, da bi dnevno dodajal samo v tisto manjšo tabelo,
ta drugo (trenutno večjo) pa bi dnevno praznil in imel notri samo zadnji uvoz iz CSVjev.
S tem izgubim sicer nekaj zapisov iz preseka, ampak je to sprejemljivo.
Sedaj pa še en razmislek:
če bi delal na ta pomožni način, ali je potem smiselno, da tista tabela, ki bi stalno rastla, sploh ima index?
Bi pa imel index na tisti, ki bi se dnevno praznila.
In potem naredim join
select * from prva where id in (select iz druge)
A si pravilno predstavljam, da bo zadeva naredila scan čez prvo tabelo (neindexirano) in iskala (po indexu) v drugi tabeli?
Dodatno: lahko naredim, da je tista dnevna (druga) tabela velika kak GB. In bi lahko v pomnilniku bila za čas poizvedbe.
A lahko join naredim, da bo ena tabela iz joina v pomnilniku, za hitrejše delovanje.
Pomožna ideja je, da bi dnevno dodajal samo v tisto manjšo tabelo,
ta drugo (trenutno večjo) pa bi dnevno praznil in imel notri samo zadnji uvoz iz CSVjev.
S tem izgubim sicer nekaj zapisov iz preseka, ampak je to sprejemljivo.
Sedaj pa še en razmislek:
če bi delal na ta pomožni način, ali je potem smiselno, da tista tabela, ki bi stalno rastla, sploh ima index?
Bi pa imel index na tisti, ki bi se dnevno praznila.
In potem naredim join
select * from prva where id in (select iz druge)
A si pravilno predstavljam, da bo zadeva naredila scan čez prvo tabelo (neindexirano) in iskala (po indexu) v drugi tabeli?
Dodatno: lahko naredim, da je tista dnevna (druga) tabela velika kak GB. In bi lahko v pomnilniku bila za čas poizvedbe.
A lahko join naredim, da bo ena tabela iz joina v pomnilniku, za hitrejše delovanje.
Zgodovina sprememb…
- spremenilo: Jure14 ()
smacker ::
Daj malo bolje opiši problem, ker če rabiš samo presek iz dveh CSV datotek, se to z hashmapom da rešit hitreje kot pisanje 120miljonov zapisov v bazo.
WarpedGone ::
A si pravilno predstavljam, da bo zadeva naredila scan čez prvo tabelo (neindexirano) in iskala (po indexu) v drugi tabeli?
Ne.
Dokler baze ne vprašaš točno kako namerava izvest konkreten SQL, ne veš kako ga nemarava izvest - takšen ali drugačen EXPLAIN.
Hashmap ... po možnosti v kakšni javasranjeimplementaciji ...
I'm outahere.
Zbogom in hvala za vse ribe
smacker ::
WarpedGone je izjavil:
Hashmap ... po možnosti v kakšni javasranjeimplementaciji ...
Kaj misliš, kaj je SQL index? Zakaj bi se ubadal z SQL, da vem pridobiš točno določeno funkcionalnost, če lahko isto funkcionalnost implementiraš s par vrsticami kode v vsakem višjem programskem jeziku.
Jure14 ::
Daj malo bolje opiši problem, ker če rabiš samo presek iz dveh CSV datotek, se to z hashmapom da rešit hitreje kot pisanje 120miljonov zapisov v bazo.
EXPLAIN
Torej:
2 CSV datoteki, dnevno se dodajajo zapisi v obe. V eno malo hitreje kot v drugo.
V eni je samo ta niz 45 znakov,
v drugi je en stolpec ta niz 45 znakov, drugi stolpec pa je podatek (tudi ena klobasa znakov).
Jaz bi rad občasno pognal neko zadevo (ker ne vem kako drugače, sem probal z uvozom v SQL in join), da mi vrne vrstice, kjer se tistih prvih 45 znakov ujema.
smacker ::
Hashmap (oz. hashtable, hashset - različni jeziki imajo različno poimenovanje) je podatkovna struktura z zapisi v obliki key=>value, ki omogoča hitre poizvedbe tipa "ali key obstaja v hashmapu". V večini programskih jezikov maš to že implementirano, tak da samo kličeš funkciji za vstavljanje(insert) in preverjanje, če vsebuje ključ(hasKey).
Najprej prebereš datoteko z id-ji. V hashmap shraniš vse zapise iz datoteke. Kot key nastaviš id, kot value pa bool false (ker ni nobenega podatka).
Nato prebereš zapise iz druge datoteke. Ko greš čez zapise (vrstico po vrstico), preverjaš če se trenutni id nahaja v hashmapu. Če se, ga shraniš, drugače greš naprej.
Najprej prebereš datoteko z id-ji. V hashmap shraniš vse zapise iz datoteke. Kot key nastaviš id, kot value pa bool false (ker ni nobenega podatka).
Nato prebereš zapise iz druge datoteke. Ko greš čez zapise (vrstico po vrstico), preverjaš če se trenutni id nahaja v hashmapu. Če se, ga shraniš, drugače greš naprej.
Zgodovina sprememb…
- spremenil: smacker ()
Jure14 ::
WarpedGone ::
Kaj misliš, kaj je SQL index?
Lahko je marsikaj, hashmap je le ena (redka) možnost. Neki je uporaba orodja ki stvar že ima ornk implementirano, neki druzga pa ubadanje s polizdelki in peglanje nebroja njihovih problemov.
>> Kaj pa če je podatkov 30GB? Pomnilnika pa 8?
Irelevantno, 100% obdelava se zgodi v pomnilniku. Ali bo zadeva najprej komplet vse prebrala v pomnilnik, ali bo brala sproti je na končnem času vseeno. Razlika lahko nastane šele ko do istega podatka dostopaš več kot enkrat - kolikokrat se bo stvar prebrala v pomnilnik.
Ali so ključi vsaj v eni datoteki unique?
Če niso, kolikšen % je število enoličnih vrednosti glede na celoto?
Ali maš MySQL postavljen samo v ta namen ali je to že neki kar imaš v druge namene?
Na koncu to bo stvar mogu narest nekdo, ki ve kaj in s čim točno to dela.
Zbogom in hvala za vse ribe
Jure14 ::
>>Ali so ključi vsaj v eni datoteki unique?
Ja.
V eni so uniq, v drugi pa se lahko pojavi duplikat, ampak se ga lahko ignorira.
>>Ali maš MySQL postavljen samo v ta namen ali
>>je to že neki kar imaš v druge namene?
Ja. Najprej sem delal z MS SQL, ampak ni šlo preko 10GB baze.
Ja.
V eni so uniq, v drugi pa se lahko pojavi duplikat, ampak se ga lahko ignorira.
>>Ali maš MySQL postavljen samo v ta namen ali
>>je to že neki kar imaš v druge namene?
Ja. Najprej sem delal z MS SQL, ampak ni šlo preko 10GB baze.
WarpedGone ::
Če lahko, dej oba fajla zazipaj in jih obesi nekam od kjer ju lahko potegnem dol.
Me resno srbi, kolk hitro lahko stvar našminkam. Če mi rata, dobiš recept.
Me resno srbi, kolk hitro lahko stvar našminkam. Če mi rata, dobiš recept.
Zbogom in hvala za vse ribe
BRBR ::
Da bi kaj napredovalo ne vidim. Ti je že bilo povedano.
V škatlo daj SSD disk če ga še nimaš. Gor naredi en folder in tega poturi v mysql ini file kot tmp file handler. Restart mysql. In skoraj gotovo bo bolje.
Vsa ostala znanost pride na vrsto po tem dejanju - pri tvoji količini podatkov.
T.j. ko stvar zaženeš poglej v mysql procese, in tam ti piše, tvoj sql --> Copying to tmp table on disk
če je disk SSD bo pač hitrejše.
V škatlo daj SSD disk če ga še nimaš. Gor naredi en folder in tega poturi v mysql ini file kot tmp file handler. Restart mysql. In skoraj gotovo bo bolje.
Vsa ostala znanost pride na vrsto po tem dejanju - pri tvoji količini podatkov.
T.j. ko stvar zaženeš poglej v mysql procese, in tam ti piše, tvoj sql --> Copying to tmp table on disk
če je disk SSD bo pač hitrejše.
Zgodovina sprememb…
- spremenil: BRBR ()
WarpedGone ::
Gor pa obesiš SW ki se 99,99% časa ubada sam s sabo (garbage collection, ...)
Zbogom in hvala za vse ribe
Jure14 ::
Bom zadevo spremenil tako, da odstranim SQL, pa malo poenostavim vse skupaj.
Sem gledal c# Hashtable razred, pa me zanima, ali ta zadeva uporablja kakšna drevesa ali kaj podobnega za dodajanje/iskanje, ali je to en navaden linearen array, pa iskanje od prvega do zadnjega elementa?
Sem gledal c# Hashtable razred, pa me zanima, ali ta zadeva uporablja kakšna drevesa ali kaj podobnega za dodajanje/iskanje, ali je to en navaden linearen array, pa iskanje od prvega do zadnjega elementa?
smacker ::
Hash tabele uporablja zgoščevalno funkcijo (hash). Pri dodajanju elementov, se s to funkcijo iz keya izračuna index v arrayu, kamor se mora element shranit. Ko delaš poizvedbo ali key obstaja, se s funkcijo zračuna index, kjer se bi element moral nahajt, nato pa se pogleda ali je v arrayu na tem indexu kaj shranjeno. Vse skupaj se rahlo zakomplicira, ker se več različnih keyev lahko preslika na isti index, zato teoretična časovna zahtevnost ni čisto O(1).
Hash table @ Wikipedia
Hash table @ Wikipedia
Vredno ogleda ...
Tema | Ogledi | Zadnje sporočilo | |
---|---|---|---|
Tema | Ogledi | Zadnje sporočilo | |
» | SQL vprasanje (strani: 1 2 )Oddelek: Programiranje | 8314 (4993) | BivšiUser2 |
» | Normalizirana struktura - queryOddelek: Programiranje | 1714 (1334) | frudi |
» | MySQL Query VprašanjeOddelek: Izdelava spletišč | 3194 (2959) | overlord_tm |
» | [MySql] obratno od DISTINCTOddelek: Programiranje | 1439 (1257) | frudi |
» | [delphi] 2 bazi v eni mrežiOddelek: Programiranje | 1091 (1040) | seawolf |