Topic: atrinkimo kriterijus - masyvas

Na yra tokia situacija.
Tarkime turiu masyvą, panašų į tokį:
Array(
0 => 'reiksme 1',
1 => 'reiksme 2',
2 => 'reiksme 3',
... => ...)
Jame įrašų skaičius gali būti nuo kelių šimtų iki kelių tūkstančių (neturėtų viršyti 10000).
Ir turiu duombazėj lentelę, kurios vieno stulpelio reikšmės atitinka duoto masyvo reikšmes. taigi, kaip geriausia spręst tokią situaciją, kai man iš tos lentelės reikia traukt duomenis, kur atitinkamam stulepyje yra duotos reikšmės iš masyvo arba nėra.
tokį variantą su keliom reikšmėm, spręsdavau tiesiog keliom užklausom (skaičius lygus masyvo elementų skaičiui). bet čiuo atveju manau būtų žiauru daryt kelis tūkstančius užklausų ant smūgio. ar nėra kitokio varianto?

Su sąlyga, kad šūdo nebus...

Re: atrinkimo kriterijus - masyvas

Na čia priklauso nuo aplinkybių.

a) jeigu tokias operacijas tu atlikinėsi retai (arba čia iš vis yra vienkartinis dalykas) tai gali naudoti tokią užklausą:

SELECT *
FROM lentele
WHERE stulpelis IN ('reiksme 1', 'reiksme 2', 'reiksme 3')

Kaip su PHP pagaminti dokią užklausą? Rekomenduoju pasidomėsi join() funkcija (-;
šios užklausos blogybė yra ta, kad ji veiks lėtai ir jos jokiu būdu negalima naudoti kaip standartinio veiksmo kažkokiame puslapyje/projekte, nes rezultatai nebus geri.

b) O iš ko sudaromas tas masyvas? Kartais ne iš kitos užklausos rezultatų? Jeigu taip, tai manau galima jas atitinkamai apjungti ir iš karto gauti norimus rezultatus tiesiai iš MySQL serverio;

c) nėra..

Re: atrinkimo kriterijus - masyvas

taip, konkrečiu atveju užklausa bus atlikinėjama retai, viso labo vieną kartą į savaitę. masyvas sukuriamas iš duomenų, esančiu faile (exportas iš kažkokios programos). na su php sukonstruot užklausą man ne problema, tik norėjau sužinot kokią mysql konstrukciją tam geriausiai naudoti.

Su sąlyga, kad šūdo nebus...

Re: atrinkimo kriterijus - masyvas

Tai dar gali būti taip, kad jeigu tie duomenys faile naudojami tik užklausoje tai galimas dar toks variantas:

Su MySQL LOAD komanda galima duomenis iš failo (txt/csv) užsikrauti į kažkokia (tame tarpe ir laikina) lentelę, ir tada užklausos pagalba atlikti JOIN'ą.

Aišku, kad MySQL'as vistiek atlikinės kažkokius tai INSERT'us, tik tiek, kad jie bus N kartų greitesni negu tu darytum skaitymą su PHP ir INSERT'inimą į MySQL.

http://dev.mysql.com/doc/refman/5.0/en/load-data.html
http://dev.mysql.com/doc/refman/5.0/en/ … ables.html

Re: atrinkimo kriterijus - masyvas

na turėsiu omeny abu variantus, nes tiesa pasakius dar nežinau kokio pavidalo tas failas bus, ar jį lengva apdorot. dėkui už pasiūlymus.

Su sąlyga, kad šūdo nebus...

6 (edited by Ramex 2009-01-21 11:37:36)

Re: atrinkimo kriterijus - masyvas

Situacija tapo šiek tiek keblesnė. yra du failai. vienas atitinka anksčiau minėtas sąlygas. bet antrame įrašų skaičius yra kur kas didesnis (> 100000). taigi manau naudot užklausa su struktūra IN būtų neįmanoma (gal aš klystų?), nes čia labai svarbu, kad darbas būtų atliktas ir nebūtų nulūžimų. toliau load data kaip suprantu paima duomenis tik iš failų, tačiau mano abieju failų struktūra yra labai nestandartinė ir panaudot kaip CSV failo tikrai neįmanoma. taigi klausimas būtų toks: ar įmanoma load data atlikti ne iš failo? jei ne, tuomet ar yra kažkokia kita load data alternatyva, ar man teks tada ta išgautą duomenų struktūrą rašyti į failą ir tada naudot load data?

gal pabandysiu daugiau apie pačią esmę. man reikia patikrinti ar iš tų dviejų failų info yra duombazėj, kiekvienas įrašas. papildyti nereikia, reikia tik tikrinimo.

Su sąlyga, kad šūdo nebus...

Re: atrinkimo kriterijus - masyvas

siaip as manau kad laikina lentele butu optimaliausias variantas, susikeli info is failu o jau tada viena rimta uzklausa, bac ir viskas.

MongoDB Certified Developer
MongoDB Certified DBA
Zend Certified Engineer

Re: atrinkimo kriterijus - masyvas

na šitą dalyką aš jau kaip ir supratau iš mindes, bet man svarbu kaip tai atlikti. tarkim jei aš darau 100000 mysql_query("INSERT... kaži ar bus optimalu. toliau load data tai jis veikia tik iš failo kiek iš dokumentacijos supratau, tai reiktų man atskirai įrašyti i failą ir tada tik loadint į DB. velgi ar tai optimalu. man svarbu greitis, bet svarbiausia, kad visas procesas vyktų iki galo, t.y. be jokių nulūžimų ir panašiai.

Su sąlyga, kad šūdo nebus...

Re: atrinkimo kriterijus - masyvas

Taip. geriau padaryti 100000 INSERT'ų į lentelę, ir tada jau mysql'e knistis kur/kokie tie įrašai yra ar nėra.

Dabar dėl galimybės naudoti MySQL'o LOAD funkciją, tai ji yra gana smarkiai pritaikoma ne vien CSV formatui, ten iš esmės gali užkrauti beveik bet kokį tekstinį failą, kuriame duomenys yra sudėlioti pakankamai sistemiškai.

Jeigu jau taip būtų, kad formatas labai jau kažkoks kreivas tada daryk duomenų įkrovimą su PHP ar kita serverio pusėje naudojama kalba/scriptu.

dėl 100000 x INSERT tai rekomenduoju dayryti taip:

10000 x 10 x INSERT. Juk yra galimybė atlikti tokią užklausą:

INSERT INTO table (stulpelis1, stulpelis2)
VALUES ("reiksme1, reiksme2),
("reiksme3, reiksme4),
("reiksme5, reiksme6),
("reiksme7, reiksme8),
("reiksme9, reiksme10),
("reiksme11, reiksme12),
("reiksme13, reiksme14);

Taip pat jeigu duomenys tame tekstiniame faile yra tikrai tvarkingi, tai prieš atliekant INSERT'us galima MySQL serveriui nurodyti, kad nebūtų operacijų metų atliekami inseksų gamyba, o juos sudėti tik sukėlus visus duomenis. Sumoje tai labai pagreitina visą procesą ir mažiau apkrauną serverį.

Re: atrinkimo kriterijus - masyvas

ir siaip kad nenuluztu po panaudojimo unsetink nereikalingus dalykus, apsisaugosi nuo atminties trukumo.

MongoDB Certified Developer
MongoDB Certified DBA
Zend Certified Engineer

Re: atrinkimo kriterijus - masyvas

taigi, iškyla bėdos su duomenų patikrinimu. turiu dvi lenteles.
pagrindinę, kurios duomenis reikia check'int

+--------+--------------+------+-----+---------+----------------+
| Field  | Type         | Null | Key | Default | Extra          |
+--------+--------------+------+-----+---------+----------------+
| id     | int(11)      | NO   | PRI | NULL    | auto_increment |
| game   | int(11)      | NO   | MUL |         |                |
| ticket | int(11)      | NO   | MUL |         |                |
| price  | int(11)      | NO   |     |         |                |
| money  | int(11)      | NO   |     |         |                |
| addon  | varchar(255) | NO   |     |         |                |
+--------+--------------+------+-----+---------+----------------+

ir tą laikiną, pagal kurios duomenis tikrinama:

+--------+--------------+------+-----+---------+----------------+
| Field  | Type         | Null | Key | Default | Extra          |
+--------+--------------+------+-----+---------+----------------+
| id     | int(11)      | NO   | PRI | NULL    | auto_increment |
| game   | int(11)      | NO   | MUL |         |                |
| ticket | int(11)      | NO   | MUL |         |                |
| price  | int(11)      | NO   |     |         |                |
| money  | int(11)      | NO   |     |         |                |
| addon  | varchar(255) | NO   |     |         |                |
+--------+--------------+------+-----+---------+----------------+

kaip matot struktūra identiška, tik tiek, kad antroj lentelėj yra ~120000 įrašų, o pirmoj ~4 milijonai.
nežinau, kaip padaryti tokį fintą. teoriškai, visi įrašai kurie įra toj antrojoj laikinoj lentelėj, turėtų būti ir pirmojoj. tai man ir reikia patikrinti, ar tikrai taip yra.
tą aš darau taip:

SELECT * FROM tickets_temp AS prim
INNER JOIN tickets AS sec 
ON sec.game=prim.game AND sec.ticket!=prim.ticket AND sec.price!=prim.price AND sec.money!=prim.money
WHERE prim.game='$dl'

$dl yra nurodomas konkretus skaičius, o id nesvarbu isvis. šios užklausos man neįvykdo, scriptas nulūžta. šitą tikrinimą darau atskiram scripte, tad ten atmintis tkitiem darbam tikrai nenaudojama, problema tik šioje užklausoje. kaip galima būtų ją pakeisti?

Su sąlyga, kad šūdo nebus...

Re: atrinkimo kriterijus - masyvas

Jeigu ID nesvarbus, tai kuris laukas identifikuoja įrašą?

Galiu tik spėti, pagal tavo užklausą, kad galbūt tokio dalyko kaip ID pas tavė nėra ir apie įrašo "vienodumą" tu sprendi, jeigu atitinka visos 4 celių game, ticket, price ir money reikšmės?

šiap jeigu neklystu tau reikalintas LEFT JOIN'as (o tiksliau LEFT OUTER JOIN'as). Ir jeigu kriterijai yra 4 stulpeliai tai tikriausiai būtų naudingą turėti apjungtą indekstą ant tų 4 stulpelių.

Taip pat man neaišku, kas būna kai "lūžta scriptas"? Būna kokia klaida, ar baigėsi scriptui skirtas vykdymo laikas, ar dar kas?

Taip pat pastebėjimas: kai rašai sujungimo kriterijus tai juos reikia rašyti tokiu pačiu eiliškumu, kaip ir vardijamos lentelės, pvz.:

SELECT ...
FROM lentele_1
  INNER JOIN lentele_2 ON lentele_1.stulpelis_1 = lentele_2.stulpelis_2

Re: atrinkimo kriterijus - masyvas

matai ID ten tiesiog rodo eilės numerį, o man ir reikia patikrinti tu likusių stulpelių reikšmes.
Dėl scripto lūžimo, tai jis tiesiog vykdomas iki begalybės, t.y. nieko, kaip baltą naršyklės langą nematau. laukiau daugiau nei 5min ir vistiek rezultatų jokių. iki begalybės laukt negaliu.

Su sąlyga, kad šūdo nebus...

Re: atrinkimo kriterijus - masyvas

Jeigu yra daug duomenų, o resursai silpni, tai 5min. nėra daug. Tokias operacijas reikia ne per PHP leisti, o tiesiai mysql serveryje.

15 (edited by Ramex 2009-01-22 11:45:23)

Re: atrinkimo kriterijus - masyvas

na visas šitas dalykas daromas ant hostex serverio. bandžiau pasidares kopijas ant lokalaus serverio, kur galiu prieit prie komandines eilutės, tai irgi tas pats. paduotu tą užklausą ir vėl gaunu tik laukimą. o paskutinį kartą taip darant ir pakabinau serverį. net neįsivaizduoju, kaip galima būtų tai apeiti. duomenų ryškiai per daug.
o kažkaip dalimis negalima būtų šitos užklausos įvykdyti?

Su sąlyga, kad šūdo nebus...

Re: atrinkimo kriterijus - masyvas

Tu neišprendęs problemų jau ieškai kaip, kažką apeiti.

Pirmą pasirašyk teisingą užklausą.

Antrą ją optimizuok (indeksai ir pan.).

Trečią - gauk teisingus rezulatatus, nesvarbu, kiek tai užtruktų, ar 20min. ar 2val.

Tada galėsi kažką kito galvoti.

Re: atrinkimo kriterijus - masyvas

nevisada yra tam galimybės. užklausą pasirašiau tokią, kokią tu parodei. optimizuoti irgi klausimas ar galiu. nes ta lentelė turi savo paskirtį. o man tik reikia tikrinimą joje padaryti. laukti galutinių rezultatų tikrai negaliu, nes dasilaukiau iki to, kad ta svetainė iš hostex serverio tapo nebepasiekiama. dabar ji vėl atsigavo.

Su sąlyga, kad šūdo nebus...

Re: atrinkimo kriterijus - masyvas

Vadinasi tau reikia galingesnio serverio. Arba siųskis duomenis pas save į kompą ir ten atlik norimus veiksmus.

Re: atrinkimo kriterijus - masyvas

na sakau, dariau ant vietinio serverio. jis po tokios užklausos visiškai pakibo. bandysiu kažkaip skaidyt į daug mažesnių užklausų.

Su sąlyga, kad šūdo nebus...

20 (edited by Ramex 2009-02-24 17:14:17)

Re: atrinkimo kriterijus - masyvas

Prisireikė atgaivinti šią temą =]
man pateikiamas vienas iš failų kažkaip chrienovai exportuojamas, ko pasekoje visos lietuviškos raidės sudarkomos ("KRIšTOLO TAURėS" => "KRIsTOLO TAURfS").
bet kas blogiausia, duomenys duombazėje yra su lietuviškom raidėm. bet bėda ta, kad man tuos duomenis reikia sulyginti (iš esmės viena ar dvi raidės žodyje reikšmės nedaro. tad tiktų ir variantas, kad tokios raidės būtų ignoruojamos). tik bėda nesugalvoju kaip. kadangi visi tie žodžiai yra didžiosios raidės, o tos išdarkomos tampa mažosiomis, tai aš sugalvojau jas pakeisti į "_", kas MySQL atitinka vieną betkokį simbolį. bet šitas variantas man kažkodėl nedavė jokių rezultatų. so, any ideas?

Su sąlyga, kad šūdo nebus...