Avem o baza de date susținută de aplicații web pentru analiza datelor, în prezent, pe baza C#.NET cu EntityFramework pe server, și în principal HTML+cadre Javascript pe partea de client (web-based).
Aplicația noastră primește în mod regulat de măsurare X/Y datapoints dozate în cantități mari, de exemplu 1e6 sau mai mult, încărcate de către utilizatori sau primite de către alte infrastructuri.
În prezent, avem un tabel în MSSQL numit Values
cu id, series_id as int; x, y, z as float
. Acest tabel este BULK INSERT
completat cu datele atunci când un client se încarcă, și metadatele asociate este salvat într-un Series
masă. Total db dimensiune este, în prezent, se apropie de 1TB, 99,99% din care este Values
date.
Această abordare a fost simplu să pună în aplicare, dar are mai multe dezavantaje care au făcut complicat și lent de-a lungul timpului:
- trebuie să introduceți în bucăți pentru a nu supraîncărca IIS proces care procesează ea (în prezent 200'000 datapoints per bucată)
- IIS procesul cerințele de memorie în timpul INSERT sunt foarte mare (>1500MB pentru 200MB de date)
- introducerea este prea lent (5 milioane de înregistrări sunt 100MB, aceasta ia >30 de secunde pentru a introduce chiar folosind mai mare parte a INTRODUCE)
- timpul a INTRODUCE întreaga masă este blocat, adică doar un singur utilizator poate introduce la un moment dat
- recuperarea de date este, de asemenea, destul de lent, solicitând 1e6 înregistrări ia uneori >10 secunde
- ștergerea serie cu >1e6 înregistrări provoacă în mod regulat timeout-uri de pe web mobil.
Datele nu este niciodată parțial selectate, astfel încât nu avem nevoie să-l aibă într-un tabel. DAR este 'subtiat pentru a afișa înainte de trimis la clienti, adică 1e6 înregistrările sunt - în mod implicit, adică în 99% din cazuri de utilizare - a redus la 2000 sau 10'000 de înregistrări înainte de trimis la client. Acest lucru este cache pe client, dar dacă un client nou cereri același set, e procesat din nou. Valorile de masă are, de asemenea, un index pe series_id
care are mai mult spațiu pe disc decât o masă în sine.
Mă întreb dacă nu ar face sens pentru a schimba acest format de stocare pentru o stocare BLOB în "Valorile" cu propriile sale date format (CSV sau JSON sau binar), și - poate - coloane suplimentare cu preprocesate 'redus' seturi de date pentru afișare care poate fi împins la clienți, fără a schimba (de exemplu. în JSON). Astfel, noul Values
format de tabel ar fi ceva de genul
id, series_id, data(blob), reduced_data(blob)
și nu ar fi doar unul Value
pe Series
intrarea, nu 1e6 sau mai mult. Redus de date va fi creat odată, când încărcate de date este primit și apoi utilizate pentru a afișa atunci când clientii solicita
Voi pierde parțială selectează din values
de IDENTITATE sau X/Y valoare, dar Valorile nu sunt Selectate pe baza nimic altceva decât id
sau series_id
deci, aceasta este , în prezent, nu o limitare. Deci, aici sunt intrebarile mele:
- Are sens, la toate? Mă aștept crearea și ștergerea de o mare PATĂ de cerneală set de date să fie întotdeauna în mod semnificativ mai repede decât crearea și ștergerea de 1.000.000 singure înregistrări. Adevărat?
- Binary BLOB sau CSV/JSON/.. BLOB? Cea mai simplă abordare pentru stocare BLOB este, desigur, pentru a crea un imens CSV sau JSON bucată și salvați-l (eventual gzipped) în baza de date. Un obicei binar format de date ar fi chiar mai mici, dar ar trebui să fie convertite în JSON înainte de trimis la clienti.
Am un sentiment suplimentar de hassle vine cu date binare formate nu poate fi în valoare de ea și e mai bine să gzip CSV/JSON blob decât să inventeze un format binar. Adevărat?
Cât despre alte dezavantaje de Pete care eu nu pot fi chiar conștienți de? Limitări de dimensiune nu pare a fi o problemă, varbinary(MAX)
este suficient. N-am nevoie de un index pe valorile în interiorul blob, doar pe metadatele (care este în tabelul de Serie).
Gândurile?