時序

以與應用程序無關的方式有效地儲存實時日內數據

  • August 22, 2016

處理實時日內數據儲存的最佳方法是什麼?

對於個人研究,我總是只從平面文件導入記憶體(歷史 EOD),​​所以我對此沒有太多經驗。我目前正在從事一個附帶項目,該項目需要從外部提要每分鐘更新每日股票報價。就目前而言,我認為任何流行的數據庫解決方案都應該在這種情況下不費吹灰之力地處理它。但我希望採用的解決方案能夠在需要實時刻度時輕鬆擴展

Marko提到了一個**類似的問題**,儘管它主要是針對R的。我正在尋找一種可用於輕量級 Web 前端(PHP/Ruby/Flex)和分析後端(C++RPython,尚不知道)的通用數據儲存。

chrisaycock提到 的面向列的數據庫應該是最可行的解決方案。而且似乎是這樣

但我不確定我是否了解某些範例性使用場景中面向列儲存的所有復雜性:

  • 為前端圖表獲取特定程式碼的全部或部分價格數據
    • 基於行的解決方案相比,獲取價格數據應該更快,因為它是順序讀取。但是將多個程式碼儲存在一個地方會如何影響這一點呢?例如,像“選擇所有時間戳和價格數據,其中ticker 等於某物”這樣的語句。我不必比較我獲取的每一行的程式碼嗎?在我必須為某些前端應用程序提供完整數據的情況下,為請求的儀器提供原始平面文件不是更有效嗎?
  • 在後端執行的分析
    • 例如計算股票的單個值(例如變異數、最近 x 天的回報)和相關的時間序列(每日回報、技術指標等)。獲取計算的輸入數據應該像前面的情況一樣更有效,但是寫入呢?我看到的收穫是批量寫入最終結果(例如每個時間戳的計算指標值),但我仍然不知道數據庫如何處理我在一個表中的不同程式碼的混搭。水平分區/分片是否會自動為我處理它,還是我最好手動拆分為每個儀器結構的表(這似乎不必要的麻煩)?
  • 使用新的傳入報價更新數據庫
    • 在這裡使用基於行的方向會更有效,不是嗎?更新聚合數據(例如每日 OHLC 表)也是如此。這不會是一個可能的瓶頸嗎?

所有這些都是在可用的開源解決方案的背景下進行的。我最初想到的是InfiniDBHBase,但我也看到這裡也提到了MonetDBInfoBright 。**正如chrisaycock引用的問題中提到的那樣,我真的不需要“生產質量”(至少現在還不需要),那麼這是否會比其他任何一個更好的選擇?

最後一個問題 - 大約從哪個載入點開始需要專門的時間序列數據庫?不幸的是,在這種情況下, kdb+FAME之類的東西超出了範圍,所以我正在考慮使用標準關係數據庫( MySQL/PostgreSQL)或鍵值儲存(如Tokyo / Kyoto Cabinet的)在商品硬體上可以做多少B+ 樹)——真的是死胡同嗎?由於我的應用程序不是關鍵任務,或者甚至是不必要的預防措施,我是否應該堅持使用上述一些面向列的解決方案?

提前感謝您對此的意見。如果某些部分過於復雜,請在評論中告訴我。我會嘗試進行相應的修改。

編輯:

嚴格來說, HBase似乎不是一個面向列的儲存,而是一個稀疏的、分佈式的、持久的多維排序映射,所以我已經從原始問題中劃掉了它。

經過一些研究,我主要傾向於InfiniDB。它具有我需要的所有功能,支持SQL(標準MySQL連接器/包裝器可用於訪問)和完整的DML子集。開源版本中唯一缺少的是動態壓縮和擴展到集群。但考慮到它是免費的,我想它仍然物有所值。

由於記憶體效率,面向列的儲存*讀取速度更快。*查看您的範例查詢:

select price, time from data where symbol = `AAPL

在這裡,我關註三列:pricetimesymbol。如果所有分時按行儲存,則數據庫必須通讀所有行才能搜尋品種。它在磁碟上看起來像這樣:

IBM | 09:30:01 | 164.05; IBM | 09:30:02 | 164.02; AAPL | 09:30:02 | 336.85

因此,軟體必須跳過價格和時間條目才能讀取符號。這將導致每個刻度的記憶體未命中!

現在讓我們看一下面向列的儲存:

IBM | IBM | AAPL; 09:30:01 | 09:30:02 | 09:30:02; 164.05 | 164.02 | 336.85

這里數據庫可以順序掃描符號列表。這是記憶體高效的。一旦軟體擁有代表感興趣的符號位置的數組索引,數據庫就可以通過隨機訪問跳轉到特定的時間和價格條目。(您可能會注意到,這些列實際上是關聯數組;每列中的第一個元素指的是聚合中的第一行,因此跳轉到第N行意味著只需訪問每個數組中的第N個元素。)

可以想像,面向列的儲存在分析過程中確實大放異彩。為了計算每個交易品種價格的移動平均值,數據庫將對交易品種列進行索引排序以確定價格條目的正確排序,然後以連續(順序)佈局的價格開始計算。再次,記憶體高效。


除了面向列的佈局之外,許多真正新的數據庫還在執行計算時將所有內容儲存**在記憶體中。**也就是說,如果數據集足夠小,軟體會將整個滴答歷史讀入記憶體,這將在執行查詢時消除頁面錯誤。因此,它永遠不會訪問磁碟!

kdb+ 所做的第二個優化是它會自動列舉 text。(此功能的靈感來自Lisp 符號)。因此搜尋特定股票不涉及典型的字元串搜尋;它只是初始列舉查找之後的整數搜尋。

通過順序儲存、記憶體分配和自動文本列舉,搜尋符號實際上只是掃描數組中的整數。這就是為什麼像 kdb+ 這樣的數據庫在讀取和分析方面比普通關係數據庫快幾個數量級的原因。


正如您在問題中指出的那樣,寫作是面向列儲存的弱點。因為每一列都是一個數組(記憶體中)或文件(磁碟上),所以更改單行意味著單獨更新每個數組或文件,而不是一次簡單地流式傳輸整行。此外,在記憶體或磁碟上追加數據非常簡單,在記憶體中更新/插入數據也是如此,但在磁碟上更新/插入數據實際上是不可能的。也就是說,使用者不能在沒有大量黑客攻擊的情況下更改歷史數據。

出於這個原因,歷史數據(儲存在磁碟上)通常被認為是append-only。在實踐中,面向列的數據庫要求使用者採用雙時間或時間點模式。(無論如何,為了更好的時間序列分析和適當的合規性報告,我建議將此模式用於金融應用程序。)


我對您的應用程序了解不足,無法確定性能或生產級別的要求。我只是希望上述指南能幫助您做出明智的決定,以了解為什麼面向列的儲存通常是您進行分析的最佳選擇。

引用自:https://quant.stackexchange.com/questions/948