Съхраняване на огромни количества (прости) данни от времева линия в DB

Трябва да запазя броя на възпроизвежданията за всяка секунда на подкаст/аудио файл. Това ще доведе до проста графика на времевата скала (като графиката на „посещенията“ в Google Analytics) със секунди по оста x и възпроизвеждания по оста y.

Въпреки това, тези подкасти могат потенциално да продължат до 3 часа и 100 000 възпроизвеждания за всяка секунда не са нереалистични. Това са 10 800 секунди с до 100 000 пускания всяка. Очевидно съхраняването на всяка изиграна секунда в собствен ред е нереалистично (ще доведе до 1+ милиард реда), тъй като искам да мога да извличам тези необработени данни бързо.

Така че въпросът ми е: как най-добре да отида да съхранявам тези огромни количества данни от времевата линия?

Една идея, която имах, беше да използвам колона с текст/петна и след това да разделя със запетая възпроизвежданията, като всяка запетая представлява нова секунда (последователно) и след това числото за броя пъти, в които тази секунда е била изиграна. Така че, ако има 100 000 пускания във втора 1 и 90 000 пускания във втора 2 и 95 000 пускания във втора 3, тогава бих го съхранил така: "100 000,90000,95000, [...]" в колоната текст/петно.

Това осъществим ли е начинът за съхраняване на такива данни? Има ли по-добър начин?

Благодаря!

Редактиране: данните се проследяват към друг източник и трябва само да актуализирам необработените данни от графиката на всеки около 15 минути. Следователно бързото четене е основната грижа.

Забележка: поради естеството на този проект всяка изиграна секунда ще трябва да се проследява индивидуално (с други думи, не мога просто да проследявам „начало“ и „край“ на всяко възпроизвеждане).


person Jamie Appleseed    schedule 14.07.2010    source източник


Отговори (4)


Проблемът със съхранението на blob е, че трябва да актуализирате целия blob за всички промени. Това не е непременно нещо лошо. Използване на вашия формат: (100 000, 90 000,...), 7 * 3600 * 3 = ~75K байта. Но това означава, че актуализирате този 75K петно ​​за всяка игра за всяка секунда.

И, разбира се, петното е непрозрачно за SQL, така че „коя секунда от коя песен има най-много възпроизвеждания“ ще бъде невъзможна заявка на ниво SQL (това е основно сканиране на таблица на всички данни, за да научите това).

И има много режийни анализи, които събират и извеждат тези данни.

От друга страна. ID на подкаст (4 байта), второ отместване (2 байта без знак позволяват предавания на подкаст до 18 часа), брой възпроизвеждания (4 байта) = 10 байта в секунда. И така, без всички блокиращи разходи, 3-часова песен е 3600 * 3 * 10 = 108K байта на песен.

Ако сте го съхранили като петно, спрямо текст (блок от longs), 4 * 3600 * 3 = 43K.

И така, структурата на втория/реда е "само" два пъти по-голяма (в един перфектен свят, консултирайте се с вашия DB сървър за подробности) от двоичен блоб. Имайки предвид допълнителните предимства, които това ви предоставя по отношение на възможността да правите запитвания, това вероятно си струва да се направи.

Единственият недостатък на секунда/на ред е, че ако имате нужда от много актуализации (няколко секунди наведнъж за една песен), това е много UPDATE трафик към DB, докато при метода на blob това вероятно е една актуализация.

Вашите модели на трафик ще повлияят на това повече от всичко.

person Will Hartung    schedule 14.07.2010
comment
Благодаря за тези предимства и недостатъци – много полезно! Ще мога да получавам данните за проследяване на партиди от интервали от 15 минути (= лесно 1000 актуализации), така че това определено е плюс за blob подхода. Освен това трябва да използвам тези данни само за графиката на времевата скала, така че възможността да правя запитване към данните е маловажна. Като се има предвид това, намирам гъвкавостта на отделните редове за привлекателна (и като гледам отговорите, много хора изглежда се чувстват по същия начин). Все пак изглежда, че blob-подходът е осъществим, така че ще направя някои тестове и на двата подхода и ще видя кой работи най-добре на практика. - person Jamie Appleseed; 15.07.2010

Ще бъде ли проблематично да се използва всяка секунда и колко пускания са на базата на секунда? Това означава 10K реда, което не е лошо и просто трябва да ВМЪКВАТЕ ред всяка секунда с текущите данни.

РЕДАКТИРАНЕ: Бих казал, че тези решения са по-добри от правенето на нещо, разделено със запетая, в колона TEXT... особено след като получаването и манипулирането на данни (което казвате, че искате да направите) би било много объркано.

person zebediah49    schedule 14.07.2010
comment
Първо, благодаря за бързия отговор! Може би трябва да изясня, че не съм загрижен твърде много за логиката на актуализиране, когато самата структура на данните е толкова проста, нито съм твърде загрижен за честотата на актуализиране (само актуализирането на всеки 15 минути е приемливо). Доколкото виждам, ще ми трябват три колони: podcast_id, second и plays. За да извлека данните от графиката, ще трябва да извлека 10K записа, запитвани по външен ключ и сортирани по цяло число. Това няма ли да отнеме секунда или две само за извличане? - person Jamie Appleseed; 15.07.2010

Бих го разглеждал като проблем с ключ-стойност.

for each second played

   Song[second] += 1

end

Като релационна база данни -

song
----
name | second | plays

И хак psuedo-sql за стартиране на секунда:

insert into song(name, second, plays) values("xyz", "abc", 0)

и друг за актуализиране на втория

update song plays = plays + 1 where name = xyz and second = abc

3-часов подкаст би имал 11K реда.

person Paul Nathan    schedule 14.07.2010
comment
Благодаря за вашия отговор. 10-11K редове изглеждат много за всеки подкаст, ако трябва бързо да извлека необработените данни от графиката (за предпочитане около 200 ms). Особено след като редовете трябва да бъдат запитвани и сортирани. Имате ли опит с това колко време са необходими за извличане на 10-11K редове, когато са заявени по външен ключ и са сортирани по цяла колона? Повечето от нещата, с които съм работил досега, са около 100 реда (представляващи страници в CMS), което е съвсем различна история! - person Jamie Appleseed; 15.07.2010
comment
Ако данните се актуализират само на всеки 15 минути, тогава защо трябва да извличате необработените данни за 200 ms? Изтеглете го за 3 секунди и го кеширайте до следващата актуализация. - person WW.; 15.07.2010
comment
Не е желателно да чакате 3 секунди при първото зареждане. Особено след като повечето графики ще се отварят само няколко пъти на ден (което означава, че повечето потребители ще изпитат време за зареждане от 3 секунди). Предполагам, че бих могъл да разгледам възможността за предварително кеширане (генериране на кеша веднага след актуализации), но това ще изисква ужасно много изчислителна мощност за всички актуализирани подкасти на всеки 15 минути. - person Jamie Appleseed; 15.07.2010

Наистина зависи от това какво генерира данните..

Доколкото разбирам, искате да приложите карта, като ключът е вторият знак, а стойността е броят на пусканията.

Какви са частите в събитието, единицата работа или транзакцията, които зареждате?

Мога ли да предположа, че имате събитие за възпроизвеждане по името на подкаста, начално и крайно време и искате да заредите в картата за анализ и представяне?

Ако случаят е такъв, можете да имате маса

  • podcastId
  • secondOffset
  • playCount

всяко дори би направило актуализация на реда между началната и крайната позиция

update t set playCount = playCount +1 където podCastId = x и secondOffset между y и z

и след това последвано от вмъкване за добавяне на онези редове между началото и спирането, които не съществуват, с брой на възпроизвеждане 1, освен ако не заредите предварително таблицата с нули.

В зависимост от DB може да имате способността да настроите разредена таблица, където не се съхраняват празни колони, което прави по-ефективно.

person Rawheiser    schedule 14.07.2010