it-swarm.asia

Timeseries: SQL atau NoSQL?

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 dengan masukan 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 tersebut 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.

33
Nicolas

Secara umum, untuk dataset terstruktur seperti itu saya menduga Anda dapat menulis format data khusus yang lebih cepat untuk sebagian besar operasi harian (mis. Data kecil diambil dari waktu yang sewenang-wenang). Manfaat beralih ke alat DB standar kemungkinan dalam beberapa tambahan, misalnya permintaan ad hoc, beberapa akses, replikasi, ketersediaan, dll. Juga 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 (1000-an) tabel individual, masing-masing berisi dua kolom:

  1. waktu: baik tipe data SQL DATETIME atau tipe numerik dari beberapa Zaman (ini adalah kunci utama)
  2. nilai: 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. Itu bisa dibaca manusia (mis. Nyse_goog_dailyhighs_2010) atau (preferensi saya) acak. Either way satu set tabel metadata diperlukan, dan nama tabel acak mencegah pengembang dari menyimpulkan apa pun menjadi nama yang tidak dimaksudkan untuk disimpulkan.

(2) Data meta 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 (mis. 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 jangka 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 diasumsikan sama spasi 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 membutuhkan 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 . Tapi sekarang setiap kolom mewakili deret 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. Sebagai contoh menambahkan entitas baru sekarang membutuhkan 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: Daripada 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 berdampingan yang cepat. Atau, Anda dapat menggunakan urutan kunci utama (stempel waktu. Dataid) untuk memasukkan yang lebih cepat.

Namun, bahkan setelah mempertimbangkan variasi-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 :).

26
Pursuit

Gunakan MongoDB, Anda dapat membuat koleksi on-the-fly dengan sangat cepat. Lihatlah mengatur data Anda ke dalam basis data 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.

1
Dantalion