Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: [C#] Paras tapa säilöä mittadataa tietokantaan

Sivun loppuun

ajv [28.04.2013 22:07:10]

#

Kerään C#-sovelluksella mittadataa. Kun mittaus (testitapaus) on tehty ja tarkastettu, täytyisi mittadatat tuupata tietokantaan talteen. Näitä mittauksia harvoin täytyy testin jälkeen tarkastella, mutta ne vain täytyy olla jossain tallessa. Mittadatan formaatti tulee olemaan jotakuinkin seuraava:

class Measurement
{
    public DateTime StartTime;
    public uint SamplingFreq_ms;
    public List<List<short>> Channels;
}

Pahimmillaan kanavia on 64, joissa kussakin 30k näytettä (= ~3,6 Mt), joskin keskimäärin mittausten koko on noin 20 kanavaa ja 1000 näytettä (= ~390kt)

Eli kysymys kuuluu: miten tuo data kannattaisi tallentaa tietokantaan?

- Mittauksia tulee vuosien varrella tuhansia ja tuhansia, eli olisi hyvä saada data mahdollisimman hyvin pakattuna (binäärisenä?) kantaan.
- Mittadataan ei tulla missään tapauksessa kohdistamaan mitään hakuja
- jos mittausta halutaan joskus jälkikäteen katsella, niin se tapahtuu samalla C#-sovelluksella, eli data pitäisi pystyä helposti palauttamaan C#-sovellukseen em. oliksi.

Metabolix [28.04.2013 22:30:08]

#

Eiköhän se tosiaan kannata jotenkin pakata. Paras pakkaus riippuu datan luonteesta: onko kanavien välillä mitään korrelaatiota ja ovatko näytteet aivan satunnaisia vai jotenkin aaltomaisia.

Yksi ratkaisu on tallentaa data WAV-muodossa. Jos data edes etäisesti muistuttaa ääniaaltoa, sen voi pakata varsin tehokkaasti jollain äänen pakkaukseen suunnitellulla menetelmällä (esim. WavPack tai FLAC; tarkista tuetut kanavamäärät). Myös jotain yleiskäyttöistä pakkausalgoritmia (esim. LZMA) voi kokeilla.

ajv [29.04.2013 12:41:07]

#

Kiitokset Metabolix vastauksesta.

Data on luonteeltaan sanoisiko nyt ”vaihtelevaa”. Mittaukset sisältävät

- DC-jännitettä (hyvinkin stabiili signaali)
- Vaihtojännitteiden ja -virtojen RMS-arvoja
- Tila- ja kontrollisanoja (eli 16 boolean-tietoa pakattu yhteen 16-bittiseen integeriin, hyvinkin satunnainen data)

Generoin mittadataa alla olevalla pätkällä

m.StartTime = DateTime.Now;
m.SamplingFreq_ms = 100;
m.NumOfChannels = 64;
m.NumOfSamples = 30000;

Random rnd = new Random();
for (int ch = 0; ch < m.NumOfChannels; ch++)
{
    m.Channels.Add(new List<short>());
    for (int i = 0; i < m.NumOfSamples; i++)
    {
        m.Channels[ch].Add((short)rnd.Next(10000));
    }
}

ja tallennus (toistaiseksi tiedostoon) näin:

stream = new FileStream("C:\\Data\\test.bin", FileMode.OpenOrCreate); //new MemoryStream();
BinaryWriter writer = new BinaryWriter(stream);
writer.Write(m.StartTime.ToBinary());
writer.Write(m.SamplingFreq_ms);
writer.Write(m.NumOfChannels);
writer.Write(m.NumOfSamples);

for (int ch = 0; ch < m.NumOfChannels; ch++)
{
    for (int i = 0; i < m.NumOfSamples; i++)
    {
        writer.Write(m.Channels[ch][i]);
    }
}
stream.Close();

Raakana 3,66 Mt
7-Zipillä pakattuna .zip: 3,36Mt
7-Zipillä pakattuna .7z: 3,20Mt

Eli tuolla tilasäästöllä (8%..13%) ei ehkä maksa vaivaa pakata, mutta täytyy tutkia vielä oikealla datalla.

groovyb [29.04.2013 13:17:42]

#

ajv kirjoitti:

Eli kysymys kuuluu: miten tuo data kannattaisi tallentaa tietokantaan?

Itse serialisoisin mittauksista saadun luokan binääriksi, ja tallentaisin BLOB:ina kantaan. StartTimen sekä SamplingFreq_ms arvot laittaisin myös erikseen omiksi kentikseen (mahdollisia kyselyitä varten).

qeijo [29.04.2013 13:26:06]

#

Kun kerta "mittadataan ei tulla missään tapauksessa kohdistamaan mitään hakuja", niin miksi data pitää edes siirtää kantaan? Mitä vikaa on säilyttää serialisoituja objekteja tietostoissa, esimerkiksi indeksoituna vuosi/kk - periaatteella.

Mitä lisäarvoa tietokanta tuo tässä tapauksessa?

Grez [29.04.2013 13:54:10]

#

qeijo kirjoitti:

Mitä lisäarvoa tietokanta tuo?

Mihin vaihtoehtoon verrattuna?

qeijo [29.04.2013 14:10:43]

#

Grez kirjoitti:

qeijo kirjoitti:

Mitä lisäarvoa tietokanta tuo?

Mihin vaihtoehtoon verrattuna?

Tekstitiedostoihin...

ajv [29.04.2013 14:11:26]

#

qeijo kirjoitti:

Kun kerta "mittadataan ei tulla missään tapauksessa kohdistamaan mitään hakuja", niin miksi data pitää edes siirtää kantaan? Mitä vikaa on säilyttää serialisoituja objekteja tietostoissa, esimerkiksi indeksoituna vuosi/kk - periaatteella.

Mitä lisäarvoa tietokanta tuo?

Softa tullaan asentamaan useamman kaverin koneeseen joilla pääsy eri verkkolevyille ja kaikilla kesähessuilla/labrakoneilla ei välttämättä edes ole pääsyä verkkolevyille. Tämän pohjalta on päädytty tuohon ratkaisuun, että kaikki softan käyttämä data on tietokannassa. Myös backupit yms. rullaa automaagisesti infran puolesta.

groovyb kirjoitti:

ajv kirjoitti:

Eli kysymys kuuluu: miten tuo data kannattaisi tallentaa tietokantaan?

Itse serialisoisin mittauksista saadun luokan binääriksi, ja tallentaisin BLOB:ina kantaan. StartTimen sekä SamplingFreq_ms arvot laittaisin myös erikseen omiksi kentikseen (mahdollisia kyselyitä varten).

Hmm… tätä serialisointia mietin itsekin ensin, mutta ilmeisesti käytin väärää serialisointiluokkaa, koska se teki datasta xml:ää, ja tiedostosta tuli tolkuttoman kokoinen. Tuo on ihan hyvä idea laittaa nuo ”metatiedot” tietokantatauluu(kin), täytyy sitä vielä miettiä.

groovyb [29.04.2013 14:14:17]

#

ajv kirjoitti:

Hmm… tätä serialisointia mietin itsekin ensin, mutta ilmeisesti käytin väärää serialisointiluokkaa

BinaryFormatter

Grez [29.04.2013 15:25:30]

#

qeijo kirjoitti:

Grez kirjoitti:

qeijo kirjoitti:

Mitä lisäarvoa tietokanta tuo?

Mihin vaihtoehtoon verrattuna?

Tekstitiedostoihin...

No mutta minne ne tekstitiedostot laitetaan? Mielestäni tekstitiedosto on jotain mitä voi säilyttää tietokannassa tai esim. levyjärjestelmässä tai verkkolevyllä, ei vaihtoehto tietokannalle.

Jos tarkoitit että vaihtoehto olisi käyttäjän paikallinen levy tai esim. verkkolevy, niin tietokannassa säilyttämisen etuna on ainakin, että kaikki toisiinsa liittyvät järjestelmän tarvitsemat tiedot on yhdessä paikassa.

ajv [29.04.2013 15:34:09]

#

groovyb kirjoitti:

ajv kirjoitti:

Hmm… tätä serialisointia mietin itsekin ensin, mutta ilmeisesti käytin väärää serialisointiluokkaa

BinaryFormatter

Uuh, ihanan helppoa :) (koodit kopsattu suoraan tuolta groovyb:n linkin takaa):

FileStream fs = new FileStream("C:\\Data\\test2.bin", FileMode.OpenOrCreate);

// Construct a BinaryFormatter and use it to serialize the data to the stream.
BinaryFormatter formatter = new BinaryFormatter();
try
{
    formatter.Serialize(fs, m);
}
catch (SerializationException ex)
{
    MessageBox.Show("Failed to serialize. Reason: " + ex.Message);
}
finally
{
    fs.Close();
}

ja palautus

Measurement m2 = null;
// Open the file containing the data that you want to deserialize.
FileStream fs = new FileStream("C:\\Data\\test2.bin", FileMode.Open);
try
{
    BinaryFormatter formatter = new BinaryFormatter();

    // Deserialize the measurement from the file and
    // assign the reference to the local variable.
    m2 = (Measurement)formatter.Deserialize(fs);
}
catch (SerializationException ex)
{
    MessageBox.Show("Failed to deserialize. Reason: " + ex.Message);
    throw;
}
finally
{
    fs.Close();
}

Vähän vie enemmän tilaa tuo serialisoitu tiedosto (4Mt) kun tuo oma aikaisempi tapani (3,66Mt). Pakattuna vievät kuitenkin ~saman verran. Täytyy vielä laskeskella tarkemmin miten paljon tuota mittadataa oikeasti tulee vuositasolla, niin näkee kannattaako sitä pakata (KISS).

mietinvaan [29.04.2013 16:27:32]

#

Mittadatan määrää voisi pienentää myös esim. pääkomponenttianalyysin (PCA) avulla. Poistamalla vähiten varianssia selittäviä PCA-komponentteja tulisit samalla poistaneeksi turhia häiriöitä.

Metabolix [29.04.2013 17:05:06]

#

ajv kirjoitti:

Generoin mittadataa alla olevalla pätkällä – – Random();

Satunnaista dataa pakkaamalla et saa yhtään mitään kuvaa pakkauksen vaikutuksesta. Satunnaista dataa ei voi pakata, koska pakkaaminen perustuu nimenomaan arvauksiin ja sääntöihin. Saamasi 13 prosentin säästö perustuu siihen, että käytät vain osan lukualueesta: log(10000) / log(65536) = 0,83, eli enintään 17 prosenttia voitaisiin teoriassa saada pois. Jos käyttäisit koko lukualueen, mikään pakkaus ei enää auttaisi yhtään.

Pakkauksessa on äärimmäisen tärkeää, millaista data on ja miten algoritmi on suunniteltu. Jos haluat saada jonkin järkevän testituloksen, käytä oikeaa dataa tai yritä edes jäljitellä sitä sopivilla aaltofunktioilla ja realistisella kohinalla.

ajv kirjoitti:

- DC-jännitettä (hyvinkin stabiili signaali)
- Vaihtojännitteiden ja -virtojen RMS-arvoja

Nämä pakkautuisivat varmaankin aika hyvin äänenpakkausalgoritmeilla.

ajv kirjoitti:

- Tila- ja kontrollisanoja

Näiden pakkautuminen riippuu siitä, miten paljon bitit vaihtelevat. Joidenkin algoritmien kohdalla (ainakin ääntä pakattaessa) tulos paranee, jos saat siirrettyä sanassa ylimmiksi ne bitit, jotka muuttuvat harvoin, ja alimmiksi ne, jotka muuttuvat usein.

ajv [30.04.2013 21:07:30]

#

Hyviä pointteja. Tila- ja kontrollisanojen bittijärjestys taitaa oletuksena ollakkin tuollainen, että vähiten merkitsevät muuttuvat eniten. Mutta täytyy testata oikealla datalla sitten. Kiitokset kaikille vastaajille!

neau33 [01.05.2013 10:35:53]

#

Moi ajv!

tsekkaa tämä


Sivun alkuun

Vastaus

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

Tietoa sivustosta