Timeseries: SQL atau NoSQL?

33

Saya tidak peduli tentang perbedaan umum antara SQL dan NoSQL (atau perbedaan tradisional mereka).

Saat ini saya sedang mencari cara mengubah penyimpanan seri waktu internal kami. Mereka semua berisi data keuangan dari sejumlah sumber yang berbeda. Saat ini, kami menyimpan data kami dalam database berpemilik. Ini sangat NoSQL, yang memiliki bahasa query sendiri.

Saya tertarik pada input komunitas: Bagaimana Anda menyimpan data dalam database SQL? Apa manfaatnya menggunakan SQL di atas NoSQL, khususnya untuk deret waktu? Apakah saya gila karena mempertimbangkan menyimpan ini dalam SQL?

Kumpulan data kami terdiri dari jutaan seri waktu, dengan sekitar 10% dari jumlah ini masing-masing berisi jutaan catatan. Rangkaian waktu disusun secara hierarkis: / Pasar / Instrumen / Nilai / Frekuensi, di mana:

  • Pasar adalah pertukaran sekuritas, dll, pada dasarnya kumpulan instrumen, biasanya instrumen serupa.
  • Instrumen adalah instrumen. Ini bisa menjadi indikator (Brent Crude), ekuitas (GOOG), dll
  • Nilai adalah salah satu dari banyak jenis data untuk suatu instrumen. Ini bisa menjadi dekat, tinggi, rendah, dll
  • Frekuensi adalah frekuensi nilai deret waktu tertentu. Mingguan, harian, bulanan, centang, sewenang-wenang, dll.

Bagaimana data disimpan dalam SQL db? Satu meja besar (mungkin dipartisi oleh sesuatu), satu meja per pasar atau instrumen, satu meja per seri waktu.

Terima kasih sebelumnya.

Nicolas
sumber
1
Apakah semua deret waktu berisi metadata yang sama (yaitu kolom)?
Jack Douglas
1
Kedengarannya seperti data warehouse ... Lihat ini di SO: stackoverflow.com/q/2684462/27535
gbn
@ jack-douglas: Apakah Anda meminta itu untuk menyarankan penyimpanan data berorientasi kolom?
Nicolas
3
@ Nicolas Tidak harapan saya adalah bahwa RDBMS SQL tradisional akan cocok untuk data Anda karena a) akan lebih mudah untuk meminta, b) volume tidak terdengar besar (miliaran baris?) C) partisi tanggal terdengar alami dan / atau fitur OLAP standar. Saya bertanya tentang metadata untuk menentukan berapa banyak tabel yang Anda butuhkan. Jika setiap deret waktu memiliki metadata unik, Anda memerlukan jutaan tabel yang sepertinya bukan ide bagus pada RDBMS biasa, tetapi saya rasa Anda tidak membutuhkannya, bukan?
Jack Douglas
2
@ Nicolas telah Anda melihat ke konektor Hadoop baru untuk SQL Server . Di permukaan, skenario Anda terlihat pas.
Mark Storey-Smith

Jawaban:

26

Secara umum, untuk dataset terstruktur seperti itu saya menduga Anda dapat menulis format data khusus yang lebih cepat untuk sebagian besar operasi harian (yaitu data kecil diambil dari waktu yang sewenang-wenang). Manfaat beralih ke alat DB standar kemungkinan ada di beberapa tambahan, misalnya permintaan ad hoc, beberapa akses, replikasi, ketersediaan, dll. Lebih mudah untuk menyewa bantuan untuk mempertahankan penyimpanan data berbasis standar.

Jika saya diminta membuat database untuk menyimpan data itu, saya akan melakukan hal berikut:

Skema yang diajukan

(1) Data inti ditempatkan ke dalam banyak tabel (masing-masing 1000), masing-masing berisi dua kolom:

  1. waktu: baik tipe data SQL DATETIME atau tipe numerik dari beberapa zaman (ini adalah kunci utama)
  2. value: diketik sesuai untuk data Anda. Saya akan default ke float presisi tunggal, namun tipe data titik tetap mungkin lebih cocok untuk transaksi keuangan. Ini mungkin tidak terindeks.

Tabel ini akan menjadi cukup besar, dan Anda mungkin ingin mempartisi mereka secara manual berdasarkan (misalnya) tahun. Tetapi Anda harus memeriksa kinerja sistem dan menyetel yang sesuai.

Tabel ini membutuhkan nama unik, dan ada beberapa opsi. Mereka bisa dibaca manusia (mis. Nyse_goog_dailyhighs_2010) atau (preferensi saya) acak. Apa pun cara satu set tabel metadata diperlukan, dan nama tabel acak mencegah pengembang menyimpulkan apa pun menjadi nama yang tidak dimaksudkan untuk disimpulkan.

(2) Data met disimpan dalam tabel terpisah, seperti yang disyaratkan oleh aplikasi :

Tabel atau set tabel tambahan diperlukan untuk melacak metadata. Tabel ini akan berisi data tentang pertukaran, instrumen, nilai, frekuensi, rentang tanggal, sumber (dari mana data itu berasal), ditambah apa pun yang Anda butuhkan. Ini dipetakan ke nama tabel data.

Jika ada cukup data, pencarian ini sebenarnya bisa memberikan nama tabel dan nama database, memungkinkan semacam sharding data yang diimplementasikan sendiri (jika itu adalah penggunaan istilah yang benar). Tapi saya akan menyimpannya sebagai cadangan.

Kemudian pada lapisan aplikasi saya akan meminta tabel metadata untuk menentukan di mana data saya berada, dan kemudian melakukan pertanyaan yang relatif sederhana pada tabel data besar untuk mendapatkan data saya.

Keuntungan:

  • Pengalaman saya (yang relatif terbatas) adalah bahwa database umumnya dapat menangani sejumlah besar tabel kecil lebih mudah daripada sejumlah kecil tabel besar. Pendekatan ini juga memungkinkan pemeliharaan yang lebih mudah (misalnya membersihkan data lama, membangun kembali tabel yang rusak, membuat / memuat ulang dari cadangan, menambahkan entitas baru). Ini sepenuhnya memisahkan berbagai jenis data, jika (misalnya) Anda memiliki data pada tingkat yang berbeda, atau memerlukan jenis data yang berbeda.

  • Konsep tabel kurus ini juga harus memungkinkan akses disk cepat untuk apa yang saya duga adalah permintaan paling umum, rentang data yang berdekatan dari satu entitas. Sebagian besar aplikasi data disk I / O terbatas, jadi ini patut dipertimbangkan. Sebagai seorang komentator telah menyiratkan, ini saya menjadi aplikasi yang ideal untuk database berorientasi kolom, tetapi saya belum menemukan produk yang berorientasi kolom yang cukup utama bagi saya untuk mempertaruhkan karir saya. Skema ini menjadi sangat dekat.

Kekurangan:

  • Sekitar setengah dari ruang disk Anda didedikasikan untuk menyimpan prangko waktu, ketika cukup jujur ​​100 atau 1000 dari tabel akan memiliki data yang sama persis di kolom cap waktu. (Sebenarnya ini adalah persyaratan jika Anda ingin melakukan join table mudah).

  • Menyimpan nama tabel dan melakukan pencarian dinamis membutuhkan banyak kompleksitas aplikasi dan operasi string, yang membuat saya merasa ngeri. Tetapi tampaknya masih lebih baik daripada alternatif (dibahas di bawah).

Pertimbangan:

  • Hati-hati membulatkan bidang waktu Anda. Anda ingin nilai Anda cukup bulat untuk mengaktifkan gabungan (jika sesuai), tetapi cukup tepat untuk tidak ambigu.

  • Hati-hati dengan zona waktu dan waktu musim panas. Ini sulit untuk diuji. Saya akan menerapkan persyaratan UTC pada penyimpanan data (yang mungkin membuat saya tidak populer) dan menangani konversi dalam aplikasi.

Variasi:

Beberapa variasi yang telah saya pertimbangkan adalah:

Pelipatan data: Jika rentang waktu sama-sama diberi jarak, maka gunakan satu kolom stempel waktu dan (misalnya) 10 kolom data. Stempel waktu sekarang mengacu pada waktu kolom data pertama, dan kolom data lainnya dianggap sama-sama diberi jarak antara stempel waktu itu dan yang berikutnya. Ini menghemat banyak penyimpanan yang sebelumnya digunakan untuk menyimpan cap waktu, dengan biaya permintaan yang signifikan dan / atau kompleksitas aplikasi. Rentang yang berdekatan, permintaan entitas tunggal sekarang memerlukan lebih sedikit akses disk.

Multi-plexing: Jika beberapa seri waktu diketahui menggunakan seri waktu yang sama, maka gunakan satu timestamp dan (misalnya) 10 kolom data seperti dijelaskan di atas. Tetapi sekarang setiap kolom mewakili rangkaian waktu yang berbeda. Ini membutuhkan pembaruan ke tabel metadata, yang bukan merupakan pencarian nama tabel dan kolom. Ruang penyimpanan berkurang. Pertanyaan tetap sederhana. Namun rentang yang berdekatan, permintaan entitas tunggal sekarang memerlukan akses disk yang jauh lebih banyak.

Mega-table: Ambil konsep "multi-plexing" secara ekstrem, dan letakkan semua data ke dalam satu tabel, satu kali seri waktu per kolom. Ini membutuhkan sejumlah besar akses disk untuk rentang yang berdekatan, permintaan entitas tunggal, dan merupakan mimpi buruk pemeliharaan. Misalnya menambahkan entitas baru sekarang memerlukan perintah MODIFY TABLE pada banyak tabel TB.

Untuk diskusi tambahan tentang format ini, lihat berbagai jawaban di: Terlalu banyak kolom di MySQL

Tabel yang dinormalkan sepenuhnya: Alih-alih menggunakan banyak tabel 2 kolom, Anda bisa menggunakan satu, tabel tiga kolom, di mana kolomnya adalah waktu, dataid, dan nilai. Sekarang tabel metadata Anda hanya perlu mencari nilai ID, daripada nama nama atau kolom, yang memungkinkan mendorong lebih banyak logika ke dalam query SQL, daripada lapisan aplikasi.

Sekitar 2/3 Penyimpanan sekarang dikonsumsi dengan kolom normalisasi, jadi ini akan menggunakan banyak ruang disk.

Anda dapat menggunakan urutan kunci primer (dataid, cap waktu) untuk kueri entitas tunggal yang berdekatan dan cepat. Atau, Anda dapat menggunakan urutan kunci utama (stempel waktu. Dataid) untuk memasukkan yang lebih cepat.

Namun, bahkan setelah mempertimbangkan variasi ini, rencana saya untuk pengembangan saya berikutnya adalah banyak tabel, masing-masing dua kolom. Itu, atau metode yang segera diposting oleh seseorang yang lebih bijak dari saya :).

Pengejaran
sumber
Terimakasih banyak atas jawaban Anda. Anda telah mengangkat beberapa poin yang sangat valid. Saya sepenuhnya setuju dengan penyimpanan dalam UTC. Saya menerapkan gagasan bahwa semua data dikirim ke frontend (web, desktop & seluler) di UTC. Kami memiliki pelanggan multinasional, dan OS harus bertanggung jawab untuk melakukan konversi waktu. Saya memiliki perusahaan DBA yang mengerjakan seluruh kumpulan data kami, dan bertanya-tanya apa yang akan dihasilkan orang lain. Terima kasih lagi.
Nicolas
Sementara konsultan DBA bekerja pada penargetan instalasi SQL Server gemuk, saya akan melanjutkan pengujian dengan pengaturan BigData.
Nicolas
Mungkin ini adalah solusi yang baik tetapi aplikasi "time series" yang sebenarnya harus mendukung fungsionalitas "perbesar data", dan database di sana tidak dapat membantu dengan itu. Basis data time series lebih lanjut tentang "memperbesar" dan "memperkecil".
Roman Pokrovskij
1

Gunakan MongoDB, Anda dapat membuat koleksi on-the-fly dengan sangat cepat. Lihatlah mengatur data Anda ke dalam basis data yang terpisah, dan koleksi di dalam basis data tersebut. Pertimbangkan berapa banyak memori yang perlu Anda coba untuk menjaga setiap pecahan di dalam memori sistem - jika Anda perlu pengambilan cepat. Konyol menggunakan solusi in-house, jika ada sesuatu yang lebih segar di luar sana yang akan berkembang sesuai dengan yang Anda butuhkan. Kedengarannya seperti inisiatif yang bagus.

Dantalion
sumber
2
Bagaimana Anda menyimpan deret waktu dalam bahasa Mongo? Setiap dokumen adalah seri waktu? atau nilai cap waktu tertentu?
RockScience
Untuk melakukan ini secara efisien untuk data non-periodik, atau bahkan berkala, yang terbaik adalah melakukan pra-alokasi potongan data. Setiap potongan akan menjadi dokumen dengan sejumlah kecil data pembukuan, array ukuran tetap untuk nilai Anda, dan array ukuran tetap untuk waktu Anda. Anda kemudian akan menyimpan metadata Anda untuk seri dalam dokumen terpisah. Dalam dokumen metadata ini, pertahankan dokumen bersarang kecil yang akan bertindak sebagai pemegang buku untuk segmen data Anda, yaitu lacak indeks array saat ini, dan segmen _id.
RYS