Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: C# access 2007 ja queryt

groovyb [04.05.2010 18:04:31]

#

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|C­IP2|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ä :/

Metabolix [04.05.2010 18:17:34]

#

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

groovyb [04.05.2010 18:22:05]

#

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ä :/

groovyb [04.05.2010 20:23:15]

#

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?

groovyb [05.05.2010 11:07:33]

#

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 :(

groovyb [05.05.2010 14:08:50]

#

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

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta