Toon posts:

Matrix opslaan in database

Pagina: 1
Acties:

Vraag


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Ik werk aan een webapp met een back-end die berekeningen uitvoert met behulp van cuBLAS.
In de berekening wordt als invoer een 10'000 x 120 matrix gebruikt, welke periodiek verandert. De oude matrix blijft beschikbaar voor het reproduceren van eerdere resultaten.

De huidige versie leest de gewenste matrix in uit een file; in wezen een csv file met het volgende format:

code:
1
2
3
4
5
6
7
8
<naam>
<datum>
#rows, #columns
row1_float1, row1_float2, ... , row1_float#columns
.
.
.
row#rows_float1, row#rowsfloat2, ... , row#rowsfloat#columns


Nu wil ik toevoegen dat gebruikers ook eigen matrices kunnen toevoegen (en verwijderen). In eerste instantie dacht ik in de database per gebruiker bij te houden welke file van hun is, maar dan krijg ik een wildgroei aan files. Dus leek het mij het beste om de matrix direct in de database op te slaan.

Mijn kennis van databases is echter zeer beperkt dus heb ik gegoogled naar tutorials en op stackoverflow gezocht. De tutorials normalizen de data allemaal, wat mij volledige overkill lijkt. Ik ga nooit een individueel element uit de matrix uit de database lezen, maar altijd de hele matrix.

De data als string opslaan lukt niet, blijkbaar is dat te lang, bovendien moet ik dan alsnog text moet parsen, terwijl ik weet dat alle waarden floats zijn. Is het niet mogelijk om het als floats op te slaan?


Het front-end is een ASP.Net applicatie en het backend is CUDA/C++. Front-end slaat data op in MariaDB, ik probeer ook MariaDB database te gebruiken om de matrices op te slaan.
...

Wat heb ik geprobeerd:

Genormaliseerd opslaan van de data. Dit lukt prima, maar slaat nergens op. Bovendien kan ik mij niet voorstellen dat een query die 10'000x120 datapoints als result geeft efficiënt is als het ook met één datapoint kan.

Opslaan in een text veld, dit gaat goed voor kleine test matrices, maar de werkelijke matrix is te groot.

...

Hoe kan ik deze data efficiënt opslaan in een database? (Of is wat ik al heb gedaan toch de beste optie?) Wat mis ik?

Alle reacties


Acties:
  • 0 Henk 'm!

  • Orion84
  • Registratie: April 2002
  • Laatst online: 10:28

Orion84

Admin General Chat / Wonen & Mobiliteit

Fotogenie(k)?

Als het enige dat je met die matrix doet het inlezen van die hele matrix is en je nooit database operaties op de inhoud van die matrix doet, dan klinkt het alles behalve logisch om die matrix in de database te zetten.

Wat is er precies mis met "een wildgroei aan files" als het werkt en je in je database netjes bijhoudt welke file van wie is en dergelijke? Welk probleem voorzie je daar precies?

The problem with common sense is that it's not all that common. | LinkedIn | Flickr


Acties:
  • 0 Henk 'm!

  • The Eagle
  • Registratie: Januari 2002
  • Laatst online: 10:47

The Eagle

I wear my sunglasses at night

Ik zit ook al te denken waarom je dit in een DB zou willen. Als het toch filebased is hoe je zit te werken....zeker als je met CUDA dingen aan de slag gaat wil je (neem ik aan" iets van distributed storage oid. De vraag is hoe groot die matrixes fysiek (dus in bytes) zijn.

Verder: als je het echt in een DB wilt en het eigenlijk gewoon een hele grote textstring is, tabel maken met ID en een CLOB (character large object) of BLOB (binary large object). Die zijn speciaal voor dit soort dingen gemaakt. Maar nogmaals de vraag: waarom zou je dit in een DB trappen?

Al is het nieuws nog zo slecht, het wordt leuker als je het op zijn Brabants zegt :)


Acties:
  • +1 Henk 'm!

  • armageddon_2k1
  • Registratie: September 2001
  • Laatst online: 27-07 10:18
Tja, je wilt dus gewoon de DB als BLOB storage gebruiken lijkt me? Op zich niks mis mee. Ik zou niet je hele matrix gaan zitten normaliseren als je niet hele DB operaties uit gaat voeren. In onze eigen applicatie beuken we ook enorme XML files gewoon als BLOB een DB in en lezen het weer uit. De DB-purist gaat gruwelen, maar wij hoeven niet individuele acties op elementen in de XML uit te voeren en gebruiken het puur voor het makkelijk op kunnen halen en opslaan van vrij specifieke applicatie-data.

@Orion84 geeft dit ook al aan natuurlijk. Je kan de wildgroei aan files nou juist wel mooi beteugelen met een juist DB schema. Dan kan je per gebruiker querien etc.

Engineering is like Tetris. Succes disappears and errors accumulate.


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
@Orion84 Op dit moment staan de files op de back-end server, files zijn niet toegankelijk voor het front-end. Het front-end vraagt een lijst met beschikbare opties op waaruit de gebruiker kan kiezen. Alle opties zijn nu door iedereeen te gebruiken.

Op het moment dat de gebruiker zijn eigen matrices kan uploaden (en downloaden, je moet kunnen terughalen wat je precies geupload had), dan moet er dus sowieso een service gemaakt worden om files te managen vanuit het front-end. De database is echter voor zowel front-end en (reken)backend beschikbaar waardoor deze gebruikt kan worden om data bij beide beschikbaar te maken.

Ook moet er sowieso al bijgehouden worden wie wat mag gebruiken, dit is geen reken back-end taak. De namen en rechten komen dus sowieso al in de database terecht.

De angst voor een wildgroei aan files komt door een andere applicatie waar gebruikers custom templates kunnen gebruiken welke als files worden opgeslagen op de server. In de praktijk wordt er vooral veel aangemaakt en weinig weggehaald.

@eagle Op dit moment binary niet zo groot 10'000 x 120 x 8 bytes = 9,2MiB.
Als tekst dubbel zo groot bij gebruik van 8-bits characters en 16 significante digits(plus de decimaal):
10'000 * 120 * 17 = 19,5MiB

We zijn echter nu aan het kijken naar een nieuwe versie die 24x zo groot is, de huidige omvang was een concessie om de rekentijd binnen de perken te houden. Dan heb je het over 219Mib/467MiB per matrix. Lijkt niets voor degenen die met 'Big Data' werken, maar voor ons significant.

CUDA is ingezet om een rekentijd van een paar uur terug te brengen naar een paar minuten, waardoor het mogelijk is geworden om verschillende opties (eigen matrices) door te rekenen om de effecten te bekijken. Iets andere schaal als waar jij mogelijk aan denkt.

Acties:
  • +1 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 30-09 16:40

Janoz

Moderator Devschuur®

!litemod

Ach, wildgroei ga je niet oplossen door je storage aan te passen. Of je nu straks een berg data als bestanden, of als BLOB's op je server hebt staan maakt ook niet zo heel veel uit lijkt me.

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Acties:
  • +1 Henk 'm!

Verwijderd

Topicstarter
Janoz schreef op dinsdag 6 april 2021 @ 14:39:
Ach, wildgroei ga je niet oplossen door je storage aan te passen. Of je nu straks een berg data als bestanden, of als BLOB's op je server hebt staan maakt ook niet zo heel veel uit lijkt me.
Ik begrijp je punt, maar ik zie het toch anders.

Als ik de filenaam in de database zet moet ik zelf de management code schrijven om de database en de directory synchroon te houden.

Als ik het in de database opsla, dan vervalt het hele synchronisatie probleem en de de database software voorziet in alle benodigde management tools om die blobs automatisch te managen. Of zie ik het nu verkeerd? (Ik heb nog nooit iets met blobs gedaan in een database. Maar neem aan dat dat uit mijn vragen wel duidelijk is)

Ik ga nu een test doen met @armageddon_2k1 zijn voorstel, alleen denk ik dat ik json ipv xml ga gebruiken, daar ben ik bekender mee.

Acties:
  • +1 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 30-09 16:40

Janoz

Moderator Devschuur®

!litemod

Je hebt inderdaad wel soort van gelijk. In de database heb je de synchronisatie automatisch (mits je je constraints goed hebt staan). Maar synchronisatie is maar een heel klein onderdeel van het hele 'probleem' en is ook relatief simpel (en achteraf) te implementeren met bestanden. Een simpel 'gooi alles weg wat niet in de database voorkomt' scriptje is zo geschreven.

Wat ik eigenlijk bedoel is dat het grootste werk zit in het uitzoeken en implementeren van de hele usecase om te bepalen wanneer iets weggegooid mag worden (als het te oud is? Als de gebruiker het wil verwijderen? als het te lang niet gebruikt is? ). Dat is je werkelijke probleem mbt wildgroei en dat probleem oplossen is onafhankelijk van hoe je die matrixdata opgeslagen hebt

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Acties:
  • 0 Henk 'm!

  • Matis
  • Registratie: Januari 2007
  • Laatst online: 08:08

Matis

Rubber Rocket

Mijn voorstel/werkwijze zou ook een database zijn.

Als je het wilt normaliseren kun je een User tabel aanmaken voor je gebruikers. En je maakt een Matrix tabel aan voor als je matrixes welke je als (long)blob opslaat. Die "koppel" je dan middels een user_id kolom (foreign key) aan een gebruiker uit de User tabel.

Zo kun je er eenvoudig voor zorgen dat iedereen alleen zijn eigen matrix(en) ziet en kan beheren.

LONGBLOB kan tot 4 GB gaan, dus je hebt nog wat ruimte om te groeien ;)

[ Voor 8% gewijzigd door Matis op 06-04-2021 21:51 ]

If money talks then I'm a mime
If time is money then I'm out of time


Acties:
  • 0 Henk 'm!

  • BramV
  • Registratie: Augustus 2007
  • Laatst online: 02-10 08:41
Ik zou de blob's wel in een aparte tabel zetten met een id_user en om bijv te vermijden dat je per ongeluk een select * met blobs doet.
Backup en restore na crash zou op de langere termijn wel vervelend kunnen gaan worden.

Acties:
  • 0 Henk 'm!

  • Matis
  • Registratie: Januari 2007
  • Laatst online: 08:08

Matis

Rubber Rocket

BramV schreef op woensdag 7 april 2021 @ 09:41:
Ik zou de blob's wel in een aparte tabel zetten met een id_user en om bijv te vermijden dat je per ongeluk een select * met blobs doet.
Klopt. Maar dat is tevens een onderdeel van de normalisatie. Want er is een 1-op-veel relatie User --> Matrix
Backup en restore na crash zou op de langere termijn wel vervelend kunnen gaan worden.
Maar data is data toch? 1TB aan tekstuele data is toch net zo "problematisch" als 1TB aan BLOBs?

If money talks then I'm a mime
If time is money then I'm out of time


Acties:
  • 0 Henk 'm!

  • matthijsln
  • Registratie: Augustus 2002
  • Laatst online: 02-10 16:57
Waar ik meteen aan dacht is een extensie voor PostgreSQL, namelijk PostGIS. Deze heeft ook ondersteuning heeft voor rasters (een andere naam voor matrices - ze kunnen ook een geografische referentie hebben maar dat is niet verplicht). Deze worden binair opgeslagen en in combinatie met 'The Oversized-Attribute Storage Technique' (TOAST) van PostgreSQL worden grote kolommen (zoals blobs of rasters) gecomprimeerd opgeslagen.

Als je met heel grote matrices gaat werken kan je toch tegen limieten in de database aanlopen, zoals de maximale blob grootte of met performance. Vooral als je de rasters niet binair opslaat maar als ongecomprimeerde tekst. PostGIS ondersteunt daarom ook 'outdb' rasters in een bestand. Het zal van je use-case afhangen wat goed werkt.

Dit is om wat achtergrond te geven, niet dat je meteen van MariaDB zou moeten overstappen maar het is dus niet zo'n gek idee wat je hebt.

In plaats van een raster op te slaan als tekst kan je trouwens ook een binair formaat zoals TIFF gebruiken (ook veel gebruikt in de GIS wereld), dat rasters/matrices ondersteunt met compressie, tiling en door veel (GIS/analyze) tools ondersteunt wordt. Waarschijnlijk overkill omdat je C++ programma dan een library nodig heeft, maar aangezien jullie toch al CUDA gebruiken misschien niet eens zo gek idee.

Als je je raster binair gaat opslaan zou ik wel voor iets als PostGIS rasters/TIFF's kiezen (een standaard bestandsformaat). Deze hebben standaard ondersteuning voor metadata zoals breedte/hoogte/aantal bands/datatypes/tiling/overviews/compressie en dergelijke zodat je niet je eigen homegrown formaat hoeft te verzinnen en er is al een heel ecosysteem om die formaten.

Acties:
  • 0 Henk 'm!

  • The Eagle
  • Registratie: Januari 2002
  • Laatst online: 10:47

The Eagle

I wear my sunglasses at night

Het voordeel van alles in 1 DB opslaan is dat het heet makkelijk is qua backup en recovery. Een point in time is een PIT van 1 DB en je hoeft geen rekening te houden met states buiten de DB (lees: bestanden ergens op disk). Een consitente PIT backup maken van een app over meerdere platforms is, tenzij de hele boel plat mag, vrijwel ondoenlijk.

Daarentegen praten we hier wel over potentieel 500Mbyte aan data per matrix. Als je dat in een LOB opslaat staat het logisch weliswaar bij elkaar. Maar komt het fysiek in 1 datafile te staan welke het DBMS sequentieel uitleest. Met een hoop IO als gevolg.

Je geeft aan dat die data periodiek ververst wordt. Hoeveel matrices worden er dan ververst? Als dat er meerdere zijn, zou ik gezien de leespatronen in een RDBMS wellicht kiezen voor een online tabel en een archieftabel, waarbij je de online tabel laat cachen in het geheugen. Anders wordt je gek van alle leesacties van schijf. Moet ik wel bij zeggen dat ik niet weet of MariaDB de mogelijkheid ondersteunt om een LOB te cachen.

Alternatief: een external tabel maken die naar een filelocatie verwijst. Dan zou ik er ook twee doen (archief en online).

Maar iets zegt me dat je een matrix van 500MB die je met CUDA achtige zaken wilt processen, gewoon liefst direct in ram wilt kunnen lezen, en dus niet sequentieel maar parallel in wilt kunnen lezen. Vanaf disk kan dat uiteraard met je tooling; vanuit een DB wordt dat lastiger want die kan de data in de kolom niet splitsen.

Wat ik in vergelijkbare gevallen wel eens heb gedaan is Hive ingezet (MySQL like MPP DWH op Hadoop). Daar kun je ook kiezen voor managed of external tables maar wel parallel werken. Having said that: als je toch aan de Hadoop gaat en met files gaat werken, waarom zou je dan Hive gebruiken :?


Last: volgens mij leent jouw use case zich uitstekend om cloudnative dingen te doen. Is dat een overweging, en zo ja welke cloud dan?

Al is het nieuws nog zo slecht, het wordt leuker als je het op zijn Brabants zegt :)

Pagina: 1