Penyimpanan data terbaik untuk miliaran baris


87

Saya harus bisa menyimpan sedikit data (sekitar 50-75 byte) untuk miliaran catatan (~ 3 miliar / bulan selama setahun).

Satu-satunya persyaratan adalah penyisipan cepat dan pencarian cepat untuk semua catatan dengan GUID yang sama dan kemampuan untuk mengakses penyimpanan data dari .net.

Saya adalah orang SQL server dan saya pikir SQL Server dapat melakukan ini, tetapi dengan semua pembicaraan tentang BigTable, CouchDB, dan solusi nosql lainnya, itu terdengar semakin seperti alternatif untuk RDBS tradisional mungkin yang terbaik karena pengoptimalan untuk kueri dan penskalaan terdistribusi. Saya mencoba cassandra dan perpustakaan .net saat ini tidak dapat dikompilasi atau semuanya dapat berubah (bersama dengan cassandra itu sendiri).

Saya telah melihat banyak penyimpanan data nosql yang tersedia, tetapi tidak dapat menemukan satu pun yang memenuhi kebutuhan saya sebagai platform siap produksi yang tangguh.

Jika Anda harus menyimpan 36 miliar rekaman kecil dan datar sehingga dapat diakses dari .net, apa yang akan dipilih dan mengapa?


Ya, nomor saya benar. Saat ini kami memiliki banyak data yang masuk ke sistem, tetapi kami menggabungkannya dan hanya menyimpan jumlah agregat sehingga kami kehilangan data per rekaman dan hanya mempertahankan jumlah data per jam. Karena persyaratan bisnis, kami ingin mempertahankan setiap rekaman seperti aslinya dan itu adalah 3Bil baris / bulan.
Jody Powlette

Anda telah mengajukan beberapa pertanyaan bagus. Jawabannya adalah: 95% waktu naik sudah cukup - datanya sudah tertunda dalam jumlah variabel jadi saya harus menyinkronkannya setelah fakta jadi turun untuk waktu yang singkat bukan masalah besar. Kehilangan sisipan atau bahkan ribuan sisipan bukanlah akhir dari dunia. Kehilangan data satu hari akan sangat buruk. Konsistensi juga tidak terlalu penting. Pada dasarnya setelah menyisipkan baris 30Mil dalam sehari, saya perlu mengambil semua baris dengan GUID yang sama (mungkin 20 baris) dan cukup yakin saya akan mendapatkan semuanya kembali.
Jody Powlette

Apakah Anda membuang 30 juta baris sehari dalam pekerjaan batch terjadwal harian / jam, atau mereka datang dalam fluks konstan satu per satu?
Remus Rusanu

Data datang dari situs FTP ... file masuk terus menerus dan saya memiliki proses yang mem-parsing file dan saat ini menghasilkan data agregat dan memasukkan nilai agregat (mungkin 1000 baris) sebagai transaksi. Proses baru perlu memasukkan ratusan ribu baris dari setiap file yang masuk, mungkin menggunakan penyisipan massal akan menjadi cara paling efisien untuk melakukannya.
Jody Powlette

Kedengarannya seperti pekerjaan ETL untuk SSIS dan SQL Server. Mereka memegang rekor dunia untuk ETL, dengan kecepatan unggah lebih dari 2TB / jam: blogs.msdn.com/sqlperf/archive/2008/02/27/etl-world-record.aspx
Remus Rusanu

Jawaban:


103

Menyimpan ~ 3,5TB data dan memasukkan sekitar 1K / detik 24x7, dan juga membuat kueri pada tingkat yang tidak ditentukan, dimungkinkan dengan SQL Server, tetapi ada lebih banyak pertanyaan:

  • persyaratan ketersediaan apa yang Anda miliki untuk ini? 99,999% uptime, atau apakah 95% cukup?
  • persyaratan keandalan apa yang Anda miliki? Apakah melewatkan sisipan menghabiskan biaya $ 1 juta?
  • persyaratan pemulihan apa yang Anda miliki? Jika Anda kehilangan data satu hari, apakah itu penting?
  • persyaratan konsistensi apa yang Anda miliki? Apakah tulisan perlu dijamin akan terlihat pada bacaan berikutnya?

Jika Anda memerlukan semua persyaratan yang saya soroti, beban yang Anda usulkan akan menelan biaya jutaan dalam perangkat keras dan lisensi pada sistem relasional, sistem apa pun, apa pun tipuan yang Anda coba (sharding, partisi, dll.). Sistem nosql, menurut definisi mereka, tidak akan memenuhi semua persyaratan ini.

Jadi jelas Anda telah melonggarkan beberapa persyaratan ini. Ada panduan visual yang bagus membandingkan penawaran nosql berdasarkan paradigma 'pilih 2 dari 3' di Panduan Visual untuk Sistem NoSQL :

pembanding nosql

Setelah pembaruan komentar OP

Dengan SQL Server, ini akan menjadi implementasi langsung:

  • satu tabel tunggal berkerumun (GUID, waktu) kunci. Ya, akan terfragmentasi , tetapi apakah fragmentasi memengaruhi baca-maju dan baca-maju hanya diperlukan untuk pemindaian jarak yang signifikan. Karena Anda hanya meminta GUID dan rentang tanggal tertentu, fragmentasi tidak akan menjadi masalah. Ya, ini adalah kunci yang lebar, jadi halaman non-daun akan memiliki kepadatan kunci yang buruk. Ya, itu akan menyebabkan faktor pengisian yang buruk. Dan ya, pemisahan halaman mungkin terjadi. Terlepas dari masalah ini, mengingat persyaratan, masih merupakan pilihan kunci cluster terbaik.
  • mempartisi tabel berdasarkan waktu sehingga Anda dapat menerapkan penghapusan catatan kadaluarsa secara efisien, melalui jendela geser otomatis . Tambahkan ini dengan pembuatan ulang partisi indeks online bulan lalu untuk menghilangkan faktor pengisian yang buruk dan fragmentasi yang diperkenalkan oleh pengelompokan GUID.
  • aktifkan kompresi halaman. Karena grup kunci dikelompokkan berdasarkan GUID terlebih dahulu, semua catatan GUID akan bersebelahan, memberikan kompresi halaman peluang bagus bagi untuk menerapkan kompresi kamus.
  • Anda memerlukan jalur IO cepat untuk file log. Anda tertarik pada throughput tinggi, bukan pada latensi rendah agar log dapat mengimbangi 1K sisipan / detik, jadi pengupasan adalah suatu keharusan.

Partisi dan kompresi halaman masing-masing memerlukan Enterprise Edition SQL Server, keduanya tidak akan berfungsi pada Edisi Standar dan keduanya cukup penting untuk memenuhi persyaratan.

Sebagai catatan tambahan, jika catatan berasal dari server web front-end, saya akan meletakkan Express di setiap server web dan alih-alih INSERT di bagian belakang, saya akan SENDinformasinya ke ujung belakang, menggunakan koneksi / transaksi lokal di Express yang terletak bersama dengan server web. Ini memberikan cerita ketersediaan yang jauh lebih baik untuk solusi tersebut.

Jadi begini cara saya melakukannya di SQL Server. Kabar baiknya adalah masalah yang akan Anda hadapi dipahami dengan baik dan solusinya diketahui. itu tidak berarti ini lebih baik dari apa yang bisa Anda capai dengan Cassandra, BigTable atau Dynamo. Saya akan membiarkan seseorang yang lebih berpengetahuan tentang hal-hal yang tidak ada-sql-ish untuk mendebat kasus mereka.

Perhatikan bahwa saya tidak pernah menyebutkan model pemrograman, dukungan .Net, dan semacamnya. Sejujurnya saya pikir mereka tidak relevan dalam penerapan besar. Mereka membuat perbedaan besar dalam proses pengembangan, tetapi setelah diterapkan tidak masalah seberapa cepat pengembangannya, jika overhead ORM mematikan kinerja :)


Saya menghubungkan situs Nathan dengan panas, tetapi ini bukan halaman depan slashdot;)
Remus Rusanu

@RemusRusanu: melihat migrasi dba.se. Hanya untuk mempersiapkan Anda :-) Dan +1
gbn

Sejak Microsoft SQL Server 2016, edisi Enterprise tidak lagi diperlukan untuk Partisi Tabel karena Partisi Tabel sekarang tersedia di hampir semua edisi SQL Server 2016.
TChadwick

17

Berlawanan dengan kepercayaan populer, NoSQL bukan tentang kinerja, atau bahkan skalabilitas. Ini terutama tentang meminimalkan apa yang disebut ketidakcocokan impedansi Objek-Relasional, tetapi juga tentang skalabilitas horizontal vs. skalabilitas vertikal yang lebih umum dari RDBMS.

Untuk persyaratan sederhana dari penyisipan cepat dan pencarian cepat, hampir semua produk database dapat digunakan. Jika Anda ingin menambahkan data relasional, atau bergabung, atau memiliki logika atau batasan transaksional kompleks apa pun yang perlu Anda terapkan, maka Anda menginginkan database relasional. Tidak ada produk NoSQL yang bisa dibandingkan.

Jika Anda membutuhkan data tanpa skema, Anda sebaiknya menggunakan database berorientasi dokumen seperti MongoDB atau CouchDB. Skema longgar adalah daya tarik utamanya; Saya pribadi menyukai MongoDB dan menggunakannya dalam beberapa sistem pelaporan khusus. Saya merasa sangat berguna ketika persyaratan data terus berubah.

Opsi NoSQL utama lainnya adalah didistribusikan Key-Value Stores seperti BigTable atau Cassandra. Ini sangat berguna jika Anda ingin menskalakan database Anda di banyak mesin yang menjalankan perangkat keras komoditas. Mereka bekerja dengan baik di server juga, jelas, tetapi tidak memanfaatkan perangkat keras kelas atas serta SQL Server atau Oracle atau database lain yang dirancang untuk penskalaan vertikal , dan jelas, mereka tidak relasional dan tidak baik untuk menegakkan normalisasi atau kendala. Selain itu, seperti yang Anda perhatikan, dukungan .NET cenderung tidak teratur.

Semua produk database relasional mendukung pemartisian jenis terbatas. Mereka tidak sefleksibel BigTable atau sistem DKVS lainnya, mereka tidak mempartisi dengan mudah di ratusan server, tetapi sebenarnya tidak terdengar seperti itu yang Anda cari. Mereka cukup pandai menangani jumlah catatan dalam miliaran, selama Anda mengindeks dan menormalkan data dengan benar, menjalankan database pada perangkat keras yang kuat (terutama SSD jika Anda mampu membelinya), dan partisi di 2 atau 3 atau 5 disk fisik jika perlu.

Jika Anda memenuhi kriteria di atas, jika Anda bekerja di lingkungan perusahaan dan memiliki uang untuk dibelanjakan pada perangkat keras yang layak dan pengoptimalan database, saya akan tetap menggunakan SQL Server untuk saat ini. Jika Anda menghemat uang dan perlu menjalankan ini pada perangkat keras komputasi awan Amazon EC2 kelas bawah, Anda mungkin ingin memilih Cassandra atau Voldemort sebagai gantinya (dengan asumsi Anda bisa mendapatkan keduanya untuk bekerja dengan .NET).


11

Sangat sedikit orang yang bekerja pada ukuran set multi-miliar baris, dan sering kali saya melihat permintaan seperti ini pada stack overflow, datanya tidak mendekati ukuran yang dilaporkan.

36 miliar, 3 miliar per bulan, itu kira-kira 100 juta per hari, 4,16 juta per jam, ~ 70 ribu baris per menit, 1,1 ribu baris per detik masuk ke sistem, secara berkelanjutan selama 12 bulan, dengan asumsi tidak ada waktu henti.

Angka-angka itu bukan tidak mungkin dengan selisih yang panjang, saya telah melakukan sistem yang lebih besar, tetapi Anda ingin memeriksa ulang apakah benar-benar jumlah yang Anda maksud - sangat sedikit aplikasi yang benar-benar memiliki kuantitas ini.

Dalam hal penyimpanan / pengambilan dan aspek yang cukup penting yang belum Anda sebutkan adalah menua data lama - penghapusan tidak gratis.

Teknologi normal yang dilihat adalah mempartisi, namun, pencarian / pengambilan yang berbasis GUID akan menghasilkan kinerja yang buruk, dengan asumsi Anda harus mendapatkan setiap nilai yang cocok selama periode 12 bulan penuh. Anda dapat menempatkan indeks berkerumun di kolom GUID akan mendapatkan data clusterd terkait untuk baca / tulis, tetapi pada jumlah dan kecepatan penyisipan tersebut, fragmentasi akan terlalu tinggi untuk didukung, dan akan jatuh ke lantai.

Saya juga menyarankan bahwa Anda akan memerlukan anggaran perangkat keras yang sangat layak jika ini adalah aplikasi serius dengan kecepatan respons tipe OLTP, yaitu dengan beberapa perkiraan tebakan, dengan asumsi pengindeksan overhead yang sangat sedikit, sekitar 2,7 TB data.

Di kamp SQL Server, satu-satunya hal yang mungkin ingin Anda lihat adalah edisi gudang data paralel baru (madison) yang dirancang lebih untuk memecah data dan menjalankan kueri paralel terhadapnya untuk memberikan kecepatan tinggi terhadap bagian data yang besar.


3
Dalam bioinformatika, kumpulan data miliaran baris tidak jarang. Tetapi mereka sering ditangani dengan mode streaming murni dari file datar.
Erik Garrison

3
@Erik: untuk pemrosesan aliran (mis. Hanya perlu mendeteksi kondisi tertentu, tetapi tidak perlu menyimpan data untuk kueri nanti) sesuatu seperti StreamInsight lebih baik daripada database apa pun microsoft.com/sqlserver/2008/en/us/r2 -complex-event.aspx
Remus Rusanu

2

"Saya harus dapat menyimpan sedikit data (sekitar 50-75 byte) untuk miliaran catatan (~ 3 miliar / bulan selama setahun).

Satu-satunya persyaratan adalah penyisipan cepat dan pencarian cepat untuk semua catatan dengan GUID yang sama dan kemampuan untuk mengakses penyimpanan data dari .net. "

Saya dapat memberitahu Anda dari pengalaman bahwa ini dimungkinkan di SQL Server, karena saya telah melakukannya di awal 2009 ... dan masih beroperasi hingga hari ini dan cukup cepat.

Tabel telah dipartisi dalam 256 partisi, perlu diingat bahwa ini adalah versi SQL 2005 ... dan kami melakukan persis seperti yang Anda katakan, yaitu menyimpan bit info oleh GUID dan mengambilnya dengan GUID dengan cepat.

Ketika saya keluar, kami memiliki sekitar 2-3 miliar catatan, dan pengambilan data masih cukup baik (1-2 detik jika melalui UI, atau kurang jika di RDBMS) meskipun kebijakan penyimpanan data baru saja akan digunakan.

Jadi, singkatnya, saya mengambil karakter ke-8 (yaitu di suatu tempat di tengah-tengah) dari string GUID dan SHA1 meng-hashnya dan memasukkannya sebagai int kecil (0-255) dan disimpan di partisi yang sesuai dan menggunakan panggilan fungsi yang sama ketika mendapatkan data kembali.

ping saya jika Anda membutuhkan info lebih lanjut ...


2

Artikel berikut membahas impor dan penggunaan tabel baris 16 miliar di Microsoft SQL. http://sqlmag.com/t-sql/adventures-big-data-how-import-16-billion-rows-single-table .

Dari artikel:

Berikut beberapa tip suling dari pengalaman saya:

  • Semakin banyak data yang Anda miliki dalam tabel dengan indeks berkerumun yang ditentukan, semakin lambat untuk mengimpor rekaman yang tidak diurutkan ke dalamnya. Pada titik tertentu, menjadi terlalu lambat untuk menjadi praktis.
  • Jika Anda ingin mengekspor tabel Anda ke file sekecil mungkin, jadikan itu format asli. Ini bekerja paling baik dengan tabel yang sebagian besar berisi kolom numerik karena mereka lebih kompak direpresentasikan dalam bidang biner daripada data karakter. Jika semua data Anda alfanumerik, Anda tidak akan mendapatkan banyak keuntungan dengan mengekspornya dalam format asli. Tidak mengizinkan null dalam bidang numerik dapat lebih memadatkan data. Jika Anda mengizinkan bidang menjadi nullable, representasi biner bidang akan berisi awalan 1 byte yang menunjukkan berapa banyak byte data yang akan mengikuti.
  • Anda tidak dapat menggunakan BCP untuk lebih dari 2.147.483.647 catatan karena variabel penghitung BCP adalah bilangan bulat 4-byte. Saya tidak dapat menemukan referensi tentang ini di MSDN atau Internet. Jika tabel Anda terdiri dari
    lebih dari 2.147.483.647 catatan, Anda harus mengekspornya dalam bentuk potongan
    atau menulis rutinitas ekspor Anda sendiri.
  • Mendefinisikan indeks berkerumun pada tabel yang telah diisi sebelumnya membutuhkan banyak ruang disk. Dalam pengujian saya, log saya meledak menjadi 10 kali
    ukuran tabel asli sebelum selesai.
  • Saat mengimpor sejumlah besar record menggunakan pernyataan BULK INSERT, sertakan parameter BATCHSIZE dan tentukan berapa banyak
    record yang akan dilakukan dalam satu waktu. Jika Anda tidak menyertakan parameter ini,
    seluruh file Anda akan diimpor sebagai satu transaksi, yang
    membutuhkan banyak ruang log.
  • Cara tercepat untuk memasukkan data ke dalam tabel dengan indeks berkerumun adalah dengan melakukan presort data terlebih dahulu. Anda kemudian dapat mengimpornya menggunakan pernyataan BULK
    INSERT dengan parameter ORDER.

1

Ada fakta tidak biasa yang sepertinya terlewatkan.

" Pada dasarnya setelah memasukkan 30 juta baris dalam sehari, saya perlu mengambil semua baris dengan GUID yang sama (mungkin 20 baris) dan cukup yakin bahwa saya akan mendapatkan semuanya kembali "

Hanya membutuhkan 20 kolom, indeks non-cluster di GUID akan berfungsi dengan baik. Anda bisa mengelompokkan di kolom lain untuk penyebaran data di seluruh partisi.

Saya punya pertanyaan tentang penyisipan data: Bagaimana cara memasukkannya?

  • Apakah ini sisipan massal dengan jadwal tertentu (per menit, per jam, dll)?
  • Dari sumber manakah data ini ditarik (file datar, OLTP, dll)?

Saya pikir ini perlu dijawab untuk membantu memahami satu sisi persamaan.


1

Amazon Redshift adalah layanan hebat. Itu tidak tersedia ketika pertanyaan awalnya diposting pada tahun 2010, tetapi sekarang menjadi pemain utama pada tahun 2017. Ini adalah database berbasis kolom, bercabang dari Postgres, jadi perpustakaan konektor SQL dan Postgres standar akan bekerja dengannya.

Paling baik digunakan untuk tujuan pelaporan, terutama agregasi. Data dari satu tabel disimpan di server yang berbeda di cloud Amazon, didistribusikan oleh pada distkey tabel yang ditentukan, jadi Anda mengandalkan daya CPU yang didistribusikan.

Jadi PILIHAN dan terutama SELECT yang teragregasi sangat cepat. Memuat data besar sebaiknya dilakukan dengan perintah COPY dari file csv Amazon S3. Kekurangannya adalah DELETEs dan UPDATEs lebih lambat dari biasanya, tetapi itulah mengapa Redshift tidak terutama dalam database transnasional, tetapi lebih dari platform gudang data.


0

Anda dapat mencoba menggunakan Cassandra atau HBase, meskipun Anda perlu membaca tentang cara mendesain kelompok kolom sesuai kasus penggunaan Anda. Cassandra menyediakan bahasa kuerinya sendiri tetapi Anda perlu menggunakan Java API dari HBase untuk mengakses data secara langsung. Jika Anda perlu menggunakan Hbase maka saya sarankan untuk menanyakan data dengan Apache Drill dari Map-R yang merupakan proyek Open Source. Bahasa kueri drill adalah SQL-Compliant (kata kunci dalam drill memiliki arti yang sama seperti kata kunci dalam SQL).


0

Dengan begitu banyak rekaman per tahun, Anda akhirnya akan kehabisan ruang. Mengapa tidak penyimpanan sistem file seperti xfs yang mendukung 2 ^ 64 file dan menggunakan kotak yang lebih kecil. Terlepas dari seberapa mewah orang ingin mendapatkan atau jumlah uang yang pada akhirnya akan dihabiskan untuk mendapatkan sistem dengan database apa pun SQL NoSQL .. yang mana banyak catatan ini biasanya dibuat oleh perusahaan listrik dan stasiun / penyedia cuaca seperti kementerian lingkungan yang mengontrol lebih kecil stasiun di seluruh negeri. Jika Anda melakukan sesuatu seperti menyimpan tekanan .. suhu..kecepatan angin .. kelembaban dll .. dan panduan adalah lokasi..Anda masih dapat membagi data berdasarkan tahun / bulan / hari / jam. Dengan asumsi Anda menyimpan 4 tahun data per hard-drive. Anda kemudian dapat menjalankannya pada Nas yang lebih kecil dengan cermin yang juga akan memberikan kecepatan baca yang lebih baik dan memiliki beberapa titik pemasangan .. berdasarkan tahun pembuatannya. Anda cukup membuat antarmuka web untuk pencarian Jadi membuang lokasi1 / 2001/06/01 // suhu dan lokasi1 / 2002/06/01 // temperature hanya akan membuang konten temperatur per jam untuk hari pertama musim panas dalam 2 tahun tersebut (24j * 2) 48 file kecil vs mencari database dengan miliaran record dan mungkin jutaan dihabiskan. Cara sederhana untuk melihat sesuatu .. 1,5 miliar situs web di dunia dengan Tuhan tahu berapa banyak halaman masing-masing Jika perusahaan seperti Google harus menghabiskan jutaan per 3 miliar pencarian untuk membayar komputer super untuk ini, mereka akan bangkrut. Sebaliknya mereka memiliki tagihan listrik ... beberapa juta komputer sampah. Dan pengindeksan kafein ... tahan masa depan .. terus menambahkan lebih banyak. Dan ya, di mana pengindeksan yang menggunakan SQL masuk akal, lalu hebat Membangun komputer super untuk tugas-tugas buruk dengan hal-hal tetap seperti cuaca ... statistik dan sebagainya sehingga teknisi dapat membual sistem mereka mengunyah xtb dalam x detik ... membuang-buang uang yang bisa jadi dihabiskan di tempat lain ..


-2

Simpan catatan dalam file biner biasa, satu file per GUID, tidak akan lebih cepat dari itu.


5
Apakah Anda benar-benar mengharapkan ini bekerja dengan baik?
ChaosPandion

3
Ya, membuat miliaran file di sistem file dapat merusak beberapa sistem file. Saya membuat kesalahan dengan melakukan sesuatu seperti ini, tetapi dengan hanya 1 juta dan saya cukup banyak menurunkan sistem mencoba membuka shell ke salah satu folder itu. Selain itu, kecuali jika Anda mencari berdasarkan pedoman, bagaimana mekanisme kueri seharusnya bekerja?
Rob Goodwin

Sulit untuk menebak bagaimana ini akan bekerja tanpa mengetahui berapa banyak GUID unik yang diharapkan :) Tetapi tidak ada yang lebih sederhana dari sekedar menulis ke file biasa. Dan sisipan cepat bersama dengan pencarian oleh GUID adalah satu-satunya persyaratan.
Thomas Kjørnes

Ini bisa berfungsi tetapi Anda harus membatasi jumlah file per folder. Anda harus membuat folder baru per n file. Anda bisa menggunakan substring dari guid sebagai nama folder.
TTT

1
ya, ada batasan jumlah inode untuk banyak filesystem dan saya ingat pernah mencapai batas itu pada redhat filesystem default .... batasnya sekitar 1.000.000 file atau lebih.
Dean Hiller

-3

Anda dapat menggunakan MongoDB dan menggunakan guid sebagai kunci sharding, ini berarti Anda dapat mendistribusikan data Anda ke beberapa mesin tetapi data yang ingin Anda pilih hanya di satu mesin karena Anda memilih dengan kunci sharding.

Sharding di MongoDb belum siap produksi.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.