2009-11-05 8 views
11

Я использую SQL Server для хранения исторических данных временных рядов для нескольких сотен тысяч объектов, наблюдаемых около 100 раз в день. Я нахожу, что запросы (дайте мне все значения для объекта XYZ между временем t1 и временем t2) слишком медленны (для моих нужд медленнее больше секунды). Я индексирую по метке времени и объекту.ключ-значение магазин для данных временного ряда?

Я подумал о том, чтобы использовать somethings хранилище с ключевыми значениями, например MongoDB, но я не уверен, что это «подходящее» использование такого рода вещей, и я не мог найти никаких упоминаний использования такой базы данных для данных временных рядов. в идеале, я бы смог сделать следующие запросы:

  • извлечь все данные для объекта XYZ между t1 и t2 времени
  • сделать выше, но вернуть одну точку дату в день (первый, последний , закрыто время т ...)
  • получить все данные для всех объектов для конкретной временной метки

данные должны быть упорядоченной, и в идеале он должен быть быстрым, чтобы записать новые данные, а также обновления существующих данных ,

Похоже, что мое желание запросить идентификатор объекта, а также по метке времени может потребовать наличия двух копий базы данных, индексированных по-разному, чтобы получить оптимальную производительность ... у любого есть какой-либо опыт создания такой системы, хранилище ключей или HDF5 или что-то еще? или это полностью выполнимо в SQL Server, и я просто не делаю это правильно?

+0

Облом, что никто не ответил на этот вопрос ... Я спрашиваю его снова, просто чтобы узнать, знает ли кто-нибудь что-нибудь. – btelles

ответ

3

Похоже, что MongoDB будет очень хорошим. Обновления и вставки очень быстро, так что вы можете создать документ для каждого события, такие как:

{ 
    object: XYZ, 
    ts : new Date() 
} 

Тогда вы можете индексировать поля ц и запросы будут также быстро. (Кстати, вы можете создать несколько индексов на одной базе данных.)

Как сделать ваши три запроса:

извлечь все данные для объекта XYZ между t1 и времени t2

db.data.find({object : XYZ, ts : {$gt : t1, $lt : t2}}) 

сделать выше, но возвращать одну дату точку в день (первый, последний, закрыт время т ...)

// first 
db.data.find({object : XYZ, ts : {$gt : new Date(/* start of day */)}}).sort({ts : 1}).limit(1) 
// last 
db.data.find({object : XYZ, ts : {$lt : new Date(/* end of day */)}}).sort({ts : -1}).limit(1) 

Для близких к некоторому времени, вы, вероятно, нужен пользовательский JavaScript функцию, но это выполнимо.

получить все данные для всех объектов для конкретной метку

db.data.find({ts : timestamp}) 

Не стесняйтесь спросить о user list, если у вас есть какие-либо вопросы, кто-то может быть в состоянии думать о более простом способе получать самые близкие к времени события.

+5

Я не уверен, что вы работали с временными рядами в прошлом, но такой дизайн не масштабируется. – 2010-12-14 11:29:02

+2

@ Matthieu N (или кто-либо еще) заботится о разработке? –

2

Именно поэтому существуют базы данных, специфичные для данных временных рядов. Реляционные базы данных просто недостаточно быстры для больших временных рядов.

Я использовал Fame довольно много в инвестиционных банках. Это очень быстро, но я думаю, что это очень дорого. Однако, если ваше приложение требует скорости, возможно, стоит посмотреть его.

1

Недавно я попробовал нечто подобное в F #. Я начал с формата строки в 1 минуту для соответствующего символа в файле с разделителем пространства, который имеет примерно 80 000 минут в минуту. Код для загрузки и разбора с диска был меньше 1 мс. Код для вычисления 100-минутного SMA за каждый период в файле составил 530 мс. Я могу вытащить любой фрагмент, который я хочу из последовательности SMA, как только вы подсчитали менее 1 мс. Я просто изучаю F #, поэтому есть способы оптимизации. Обратите внимание, что это было после нескольких тестовых прогонов, поэтому оно уже было в кэше Windows, но даже при загрузке с диска он никогда не добавляет к нагрузке более 15 мс.

дата, время, открытый, высокий, низкий, близкий, объем 01/03/2011,08: 00: 00,94.38,94.38,93.66,93.66,3800

Чтобы уменьшить время перерасчета сохранить I всю вычисленную последовательность индикаторов на диск в одном файле с разделителем \ n и обычно занимает менее 0,5 мс для загрузки и анализа, когда в кеше файлов Windows. Простая итерация по всем данным временного ряда, чтобы вернуть набор записей в диапазоне дат в течение 3 мс с полным годом в 1 минуту баров. Я также сохраняю ежедневные бары в отдельном файле, который загружается еще быстрее из-за более низких объемов данных.

Я использую слой .net4 System.Runtime.Caching для кэширования сериализованного представления предварительно вычисленной серии и с помощью двух гигабайтов ОЗУ, выделенных для кеша, я получаю почти 100% -ный коэффициент попадания в кеш, поэтому мой доступ к любому предварительно вычисленный индикатор, установленный для любого символа, обычно работает под 1 мс.

Вытягивание любого фрагмента данных, который требуется от индикатора, обычно меньше 1 мс, поэтому расширенные запросы просто не имеют смысла. Используя эту стратегию, я мог бы легко загрузить 10-летнюю шкалу за 1 минуту менее чем за 20 мс.

// Parse a \n delimited file into RAM then 
// then split each line on space to into a 
// array of tokens. Return the entire array 
// as string[][] 
let readSpaceDelimFile fname = 
    System.IO.File.ReadAllLines(fname) 
    |> Array.map (fun line -> line.Split [|' '|]) 

// Based on a two dimensional array 
// pull out a single column for bar 
// close and convert every value 
// for every row to a float 
// and return the array of floats. 
let GetArrClose(tarr : string[][]) = 
    [| for aLine in tarr do 
     //printfn "aLine=%A" aLine 
     let closep = float(aLine.[5]) 
     yield closep 
    |] 
2

Существует база данных с открытым исходным кодом для активной разработки (только для .NET), которую я написал. Он может хранить массивные суммы (террабайты) однородных данных в «двоичном плоском файле». Все использование ориентировано на потоки (вперед или назад). Мы активно используем его для хранения и анализа запасов в нашей компании.

Я не уверен, что это будет именно то, что вам нужно, но это позволит вам получить первые две точки - получить значения от t1 до t2 для любых серий (по одной серии для каждого файла) или просто взять одну точку данных.

https://code.google.com/p/timeseriesdb/

// Create a new file for MyStruct data. 
// Use BinCompressedFile<,> for compressed storage of deltas 
using (var file = new BinSeriesFile<UtcDateTime, MyStruct>("data.bts")) 
{ 
    file.UniqueIndexes = true; // enforces index uniqueness 
    file.InitializeNewFile(); // create file and write header 
    file.AppendData(data); // append data (stream of ArraySegment<>) 
} 

// Read needed data. 
using (var file = (IEnumerableFeed<UtcDateTime, MyStrut>) BinaryFile.Open("data.bts", false)) 
{ 
    // Enumerate one item at a time maxitum 10 items starting at 2011-1-1 
    // (can also get one segment at a time with StreamSegments) 
    foreach (var val in file.Stream(new UtcDateTime(2011,1,1), maxItemCount = 10) 
     Console.WriteLine(val); 
} 
+0

Не знаю, почему никто больше не имеет поддержки, но с опозданием благодарит вас за обмен – MrMesees

0

Я использую hdf5 как мое время хранилище серии. Он имеет ряд эффективных и быстрых стилей сжатия, которые можно смешивать и сопоставлять. Он может использоваться с несколькими языками программирования.

Я использую boost :: date_time для поля timestamp.

В финансовой сфере я создаю конкретные структуры данных для каждого из баров, тиков, сделок, котировок, ...

Я создал несколько пользовательских итераторов и использовал стандартные функции библиотеки шаблонов, чтобы иметь возможность эффективно искать конкретные значения или диапазоны записей, основанных на времени.

 Смежные вопросы

  • Нет связанных вопросов^_^