Tervehdys!
olisi pientä ongelmaa....
lähinnä nopeutta koskien :/
kyseessä on kanta joka sisältää useita tableja, joita tulee lisää sitä mukaa kun tuotteitakin tulee.
jokainen tuote -table sisältää rivejä, jopa satoja tuhansia.
kolumnit menee näin, oletetaan että kyseessä olisi vaikka 4x niminen table.
_YEAR|_MONTH|_DAY|HOUR|MINUTE|SECOND|CIP0|CIP1|CIP2|CIP3|CIP4|CIP5|CIP6|
1 2010 2 2 14 20 22 CIP 00 01 000 001 03 002
2 etc.
3
4
5
....
290000
nyt itse ongelmaan. oletetaan että minulla on eri päivämääriä vaikka 125, ja haen löytyykö kyseisiä päivämääriä kannasta, niin haussa kestää joku puoli tuntia.
haku on toteutettu tähän tyyliin: funktio palauttaa taulukon päivämääristä joita ei löydy.
public string[] CIPEXISTS(string[] Dates, string name) //Dates taulukko, sisältää päivämäärät. näitä voi olla vaikka 1000. name on taulun nimi { try { string[] Unmatched = new string[200]; int index = 0; int inds = 0; for (int c = 0; c < Dates.Length; c++) { if (Dates[c] != null) inds++; } for(int x = 0; x < inds;x++) { bool found = false; string[] Parsed = Dates[x].Split(new string[] {"-"},StringSplitOptions.None); //Tämä siksi että päivämäärä tulee muodossa esim. 2010-05-13 DBCOM.CommandText = "SELECT COUNT([_DAY]) FROM " + name + " WHERE [_YEAR]=" + Parsed[0] + " AND [_MONTH]=" + Parsed[1] + " AND [_DAY]="+Parsed[2]; READER = DBCOM.ExecuteReader(); while(READER.Read() && !found) { if (READER.GetInt32(0) != 0) //jos löytyy yksikin tällä päivämäärällä saatu tieto, muuttuu trueksi. saman päivän aikana voi tulla satoja viestejä. { found = true; } else //jos ei löydy, lisätään päivämäärä taulukkoon { Unmatched[index] = Dates[x]; index++; found = false; } } READER.Close(); } string[] NotFound = new string[index]; int NotfoundIndex = 0; for (int z = 0; z < Unmatched.Length; z++) { if (Unmatched[z] != null) { NotFound[NotfoundIndex] = Unmatched[z]; NotfoundIndex++; } } return NotFound; } catch (Exception ex) { string[] Error = { "Error: " + ex.ToString() }; return Error; } }
auttakaa miestä mäessä :/
Eikö olisi järkevämpää koota lauseke, joka hakisi kaikki tiedot kerralla?
SELECT paivays, COUNT(*) AS n FROM taulu WHERE paivays IN (pvm1, pvm2) GROUP BY paivays
Tai jos tästä tuntuu tulevan huono, niin voisi edes hakea aina yhden kuukauden tiedot kerralla tms. pienempää.
Muuten, minkähän takia ajankohta on tallennettu kuuteen erilliseen kokonaislukusarakkeeseen eikä vain yhteen DATETIME-sarakkeeseen? Yhdellä sarakkeella ehdosta tulisi yllä esittämäni kaltainen, mutta nyt joudut tekemään paljon mutkikkaammin:
WHERE (year = 1234 AND ((month = 1 AND day IN (1, 2)) OR (month = 2 AND day IN (3, 4)))) OR (year = 2345 AND ((...)))
oli helpompaa koodata kuudella eri :)
elikäs. tiedosto on 2010-05-10.log,(päivämäärä tiedostonimessä) jossa asciina
14:23:22 CIP:04:123:032:22, sarakkeitten määrä vaihtelee tuotteista riippuen, rivien määrä voi olla tuhansia.
parsetin nämä vaan erikseen ja dynaamisesti tein kolumnit sarakkeittain.
returnina hausta tarvitsen jokaisen päivämäärän takaisin muodossa "vuosi-kuukausi-päivä" jotta voin alkaa päivittämään kantaa jos koneelta uusia lokeja löytyy jotka jostain syystä eivät ole kantaan päivittyneet.
myöskin uusien tiedostojen ajo kantaan on tuskaisen hidasta, kun rivi kerrallaan mättää parsetetusta lokitiedostosta kantaan. 129päivän, 250k rivin lokitiedoston ajaminen kestää noin 2.5h
voiko yhdestä datetimestä erotella kellon ajan pois?
hakuehtoina pitäisi olla vain WHERE _YEAR = haettu AND _MONTH = haettu AND _DAY = haettu
uusia CIP viestejä tulee noin 2sek välein. tarvitsisi vain katsoa että jos ei löydy ks. päivän lokeja, ne ajetaan kantaan.
returnina tulisi saada taulukko päivämääristä joita ei löydy, jonka jälkeen toisella funktiolla tungetaan puuttuvat lokitiedostot kantaan.
olin ajatellut jotain stored queryä, jos vähän auttaisi. mutta perhanan query wizardit ei ymmärrä että tablen nimi pitäisi tulla parametrinä :(
en ainakaan osaa sellaista tehdä :/
kokeilin myös executescalar():lla, jolloin vertasin näin
//for niin monta kertaa kuin päiviä haetaan. eli yksitellen haen jokaista päivää tietokannasta ja katson löytyykö countilla > 0 DBCOM.CommandText = "SELECT COUNT([_DAY]) FROM " + name + " WHERE [_YEAR]=" + Parsed[0] + " AND [_MONTH]=" + Parsed[1] + " AND [_DAY]="+Parsed[2]; int count = DBCOM.ExecuteScalar(); if (count != 0) //jos löytyy yksikin tällä päivämäärällä saatu tieto, muuttuu trueksi. saman päivän aikana voi tulla satoja viestejä. { } else //jos ei löydy, lisätään päivämäärä taulukkoon { Unmatched[index] = Dates[x]; index++; }
ja aivan yhtä kauan kesti. ärsyttävää.
GROUP esimerkissäsi Metabolix laitoit (Pvm1, Pvm2), mitä nämä ovat?
noniin ja vähän päivitystä:
kiitokset jpa:lle (ja #ohjelmointiputkalle), nyt queryt tulee suht nopeaan (aiemmin 15min, nyt 5sek) kun
päivämääräkolumneihin sidottiin indeksi.
ongelmana pysyy nyt uusien rivien tunkeminen tietokantaan
tein stored queryn rivien lisäykselle, mutta mitään merkittävää nopeuseroa en vieläkään havainnut. tässä koodia rivien lisäyksestä:
public bool CIPINSERT(string name,int Year,int Month,int Day, int hours, int minutes, int seconds, string cip0,string cip1, string cip2, string cip3, string cip4, string cip5, string cip6) { try { //Stored queryn nimi on name+CipInsert /* Tässä itse stored query joka luodaan erillisessä funktiossa tablen luonnin yhteydessä "CREATE PROCEDURE " + name + "CipInsert AS" + "INSERT INTO " + name + " ( _YEAR, "_MONTH, _DAY," + "Hours, Minutes, Seconds, Cip0, Cip1," + "Cip2, Cip3, Cip4, Cip5, Cip6 )" + "VALUES ([@Value2], [@Value3]," + "[@Value4], [@Value5], [@Value6]," + "[@Value7], [@Value8], [@Value9]," + "[@Value10], [@Value11], [@Value12]," + "[@Value13], [@Value14])" */ DBCOM.CommandText = "EXEC " + name + "CipInsert " + Year + "," + Month + "," + Day + "," + hours + "," + minutes + "," + seconds + ",'" + cip0 + "','" + cip1 + "','" + cip2 + "','" + cip3 + "','" + cip4 + "','" + cip5 + "','" + cip6 + "'"; DBCOM.ExecuteNonQuery(); return true; } catch (Exception ex) { string error = ex.ToString(); return false; } }
yksitellen funktioon lähetetään rivi joka tietokantaan insertoidaan stored queryn kautta. for-loop jolla parsitaan rivit funktioon, ei ole nopeusongelma.
nopeus tällähetkellä on ~50 riviä sekunnissa :(
hmm. voisiko olla että jos accessin editori ja tietokanta on auki, tavara siirtyy huomattavasti hitaammin?
ajelin testiajoja editori suljettuna, nyt insert nopeus on 1rivi/millisekunti. tämä on jo ihan riittävä.
Aihe on jo aika vanha, joten et voi enää vastata siihen.