Bisakah MySQL secara wajar melakukan kueri pada miliaran baris?

283

Saya berencana menyimpan pindaian dari spektrometer massa dalam database MySQL dan ingin mengetahui apakah menyimpan dan menganalisis jumlah data ini layak atau tidak. Saya tahu kinerja sangat bervariasi tergantung pada lingkungan, tetapi saya mencari urutan besarnya: apakah permintaan akan memakan waktu 5 hari atau 5 milidetik?

Masukkan format

Setiap file input berisi proses spektrometer tunggal; setiap proses terdiri dari satu set pemindaian, dan setiap pemindaian memiliki larik titik data yang dipesan. Ada sedikit metadata, tetapi sebagian besar file terdiri dari array 32 atau 64 bit atau mengapung.

Sistem host

| ---------------- + ------------------------------- |
| OS | Windows 2008 64-bit |
| Versi MySQL | 5.5.24 (x86_64) |
| CPU | 2x Xeon E5420 (total 8 core) |
| RAM | 8GB |
| Sistem file SSD | 500 GiB |
| HDD RAID | 12 TiB |
| ---------------- + ------------------------------- |

Ada beberapa layanan lain yang berjalan di server menggunakan waktu prosesor yang dapat diabaikan.

Statistik file

| ------------------ + -------------- |
| jumlah file | ~ 16.000 |
| ukuran total | 1.3 TiB |
| ukuran min | 0 byte |
| ukuran maksimal | 12 GiB |
| berarti | 800 MiB |
| median | 500 MiB |
| total titik data | ~ 200 miliar |
| ------------------ + -------------- |

Jumlah total titik data adalah perkiraan yang sangat kasar.

Skema yang diajukan

Saya berencana melakukan hal-hal "benar" (yaitu menormalkan data seperti orang gila) dan akan memiliki runstabel, spectratabel dengan kunci asing runs, dan datapointstabel dengan kunci asing spectra.

Dataran data 200 miliar pertanyaan

Saya akan menganalisis berbagai spektrum dan bahkan mungkin beberapa berjalan, menghasilkan pertanyaan yang bisa menyentuh jutaan baris. Dengan asumsi saya mengindeks semuanya dengan benar (yang merupakan topik untuk pertanyaan lain) dan saya tidak berusaha mengocok ratusan MiB di seluruh jaringan, apakah masuk akal jika MySQL menangani hal ini?

informasi tambahan

Data pemindaian akan berasal dari file dalam format mzML berbasis XML . Daging format ini ada di <binaryDataArrayList>elemen tempat data disimpan. Setiap pemindaian menghasilkan> = 2 <binaryDataArray>elemen yang, secara bersamaan, membentuk larik 2 dimensi (atau lebih) [[123.456, 234.567, ...], ...].

Data-data ini ditulis sekali, jadi perbarui kinerja dan keamanan transaksi bukan masalah.

Rencana naif saya untuk skema database adalah:

runs meja

| nama kolom | ketik |
| ------------- + ------------- |
| id | KUNCI UTAMA |
| start_time | TIMESTAMP |
| nama | VARCHAR |
| ------------- + ------------- |

spectra meja

| nama kolom | ketik |
| ---------------- + ------------- |
| id | KUNCI UTAMA |
| nama | VARCHAR |
| indeks | INT |
| spectrum_type | INT |
| representasi | INT |
| run_id | KUNCI ASING |
| ---------------- + ------------- |

datapoints meja

| nama kolom | ketik |
| ------------- + ------------- |
| id | KUNCI UTAMA |
| spectrum_id | KUNCI ASING |
| mz | GANDA |
| num_counts | GANDA |
| indeks | INT |
| ------------- + ------------- |

Apakah ini masuk akal?


Jadi, karena Anda mungkin dapat menyimpulkan, saya adalah programmer, bukan ahli biologi di lab, jadi saya tidak tahu sains hampir sama baiknya dengan ilmuwan yang sebenarnya.

Berikut adalah plot spektrum tunggal (pemindaian) dari jenis data yang akan saya hadapi:

Tangkapan layar penampil

Tujuan dari perangkat lunak ini adalah untuk mencari tahu di mana dan seberapa signifikan puncaknya. Kami menggunakan paket perangkat lunak berpemilik untuk mencari tahu ini sekarang, tetapi kami ingin menulis program analisis kami sendiri (dalam R) sehingga kami tahu apa yang sedang terjadi di bawah lembaran. Seperti yang Anda lihat, sebagian besar data tidak menarik, tetapi kami tidak ingin membuang data yang berpotensi bermanfaat yang terlewatkan oleh algoritma kami. Setelah kami memiliki daftar kemungkinan puncak dengan mana kami puas, sisa pipa akan menggunakan daftar puncak itu daripada daftar mentah titik data. Saya kira itu akan cukup untuk menyimpan datapoints mentah sebagai gumpalan besar, sehingga mereka dapat dianalisis kembali jika perlu, tetapi hanya menyimpan puncak sebagai entri database yang berbeda. Dalam hal ini, hanya akan ada beberapa lusin puncak per spektrum, jadi hal-hal skala gila tidak boleh

haxney
sumber
8
Karena ini adalah data spektrometer massa polling A / D mentah, sepertinya sangat bodoh untuk menyimpannya dalam database. Saya akan mengambil data mentah saya, membuangnya, memprosesnya, dan menyimpan HASIL yang diproses dalam database. Hasilnya adalah (a) bentuk gelombang yang disimpan satu bentuk gelombang per baris, (b) data lain yang terkait dengan bentuk gelombang tersebut seperti kurva kalibrasi, dan (c) baris hasil dalam database. Ini akan memotong miliaran baris kembung dari desain Anda. Ketika Anda ingin menjalankan kembali analisis awal, Anda akan secara efektif mengedit beberapa parameter, menjalankan operasi komputasi raksasa, dan menyimpan hasil baru di db.
Warren P

Jawaban:

115

Saya tidak terlalu terbiasa dengan kebutuhan Anda, tetapi mungkin menyimpan setiap titik data dalam basis data sedikit berlebihan. Kedengarannya hampir seperti mengambil pendekatan menyimpan perpustakaan gambar dengan menyimpan setiap piksel sebagai catatan terpisah dalam basis data relasional.

Sebagai aturan umum, sebagian besar waktu menyimpan data biner dalam database adalah salah. Biasanya ada cara yang lebih baik untuk menyelesaikan masalah. Meskipun secara inheren tidak salah untuk menyimpan data biner dalam basis data relasional, sering kali kerugiannya lebih besar daripada keuntungannya. Database relasional, seperti namanya, paling cocok untuk menyimpan data relasional. Data biner tidak bersifat relasional. Ini menambah ukuran (sering secara signifikan) ke database, dapat merusak kinerja, dan dapat menimbulkan pertanyaan tentang mempertahankan miliaran catatan MySQL. Berita baiknya adalah bahwa ada basis data yang sangat cocok untuk menyimpan data biner. Salah satunya, meskipun tidak selalu jelas, adalah sistem file Anda! Cukup datang dengan direktori dan struktur penamaan file untuk file biner Anda,

Pendekatan lain akan menggunakan sistem penyimpanan berbasis dokumen untuk data Anda titik (dan mungkin spektrum) data, dan menggunakan MySQL untuk berjalan (atau mungkin menempatkan berjalan ke dalam DB yang sama dengan yang lain).

Krystian Cybulski
sumber
5
Mengapa dianggap salah untuk menyimpan data biner dalam database? (Bertanya sebagian karena saya penasaran tetapi juga karena saya bisa memikirkan use case untuk itu.)
15
Jika data biner tidak memiliki nilai satu per satu, itu tidak boleh disimpan sebagai baris unik. Piksel 500x325 pada gambar tidak relevan.
1
Itu poin yang sangat bagus. Kita mungkin harus menyimpan file mentah kalau-kalau kita perlu menariknya lagi nanti, tetapi analogi untuk menyimpan gambar adalah yang hebat. Kami tidak akan memerlukan akses ke setiap titik data (kecuali jika kami mengulang ekstraksi puncak), jadi menyimpan informasi statistik yang diekstrak akan jauh lebih baik.
haxney
107

Saya pernah bekerja dengan database MySQL yang sangat besar (Terabyte +). Meja terbesar yang kami miliki adalah lebih dari satu miliar baris. Ini menggunakan MySQL 5.0, jadi mungkin saja semuanya membaik.

Itu berhasil. MySQL memproses data dengan benar sebagian besar waktu. Itu sangat sulit sekalipun. (Jika Anda ingin ketersediaan enam level sigma dengan satu terabyte data, jangan gunakan MySQL. Kami adalah startup yang tidak memiliki DBA dan dana terbatas.)

Mencadangkan dan menyimpan data adalah tantangan. Diperlukan waktu berhari-hari untuk mengembalikan tabel jika perlu.

Kami memiliki banyak tabel dalam kisaran 10-100 juta baris. Setiap bergabung dengan signifikan ke meja terlalu memakan waktu dan akan memakan waktu selamanya. Jadi kami menulis prosedur tersimpan untuk 'berjalan' tabel dan proses bergabung dengan rentang 'id. Dengan cara ini, kami akan memproses data 10-100.000 baris sekaligus (Gabung dengan id 1-100.000 kemudian 100.001-200.000, dll.). Ini secara signifikan lebih cepat daripada bergabung dengan seluruh tabel.

Menggunakan indeks pada tabel yang sangat besar yang tidak didasarkan pada kunci utama juga jauh lebih sulit. Mysql 5.0 menyimpan indeks dalam dua bagian - ia menyimpan indeks (selain indeks primer) sebagai indeks ke nilai kunci primer. Jadi pencarian diindeks dilakukan dalam dua bagian: Pertama MySQL pergi ke indeks dan menarik darinya nilai kunci primer yang perlu ditemukan, kemudian melakukan pencarian kedua pada indeks kunci utama untuk menemukan di mana nilai-nilai tersebut.

Net dari ini adalah bahwa untuk tabel yang sangat besar (1-200 Juta plus baris) pengindeksan terhadap tabel lebih ketat. Anda membutuhkan lebih sedikit, indeks yang lebih sederhana. Dan melakukan bahkan pernyataan pilih sederhana yang tidak secara langsung pada indeks mungkin tidak akan pernah kembali. Di mana klausa harus mencapai indeks atau melupakannya.

Tapi semua yang dikatakan, semuanya benar-benar berhasil. Kami dapat menggunakan MySQL dengan tabel yang sangat besar ini dan melakukan perhitungan serta mendapatkan jawaban yang benar.

Mencoba melakukan analisis pada 200 miliar baris data akan membutuhkan perangkat keras yang sangat canggih dan banyak pegangan tangan dan kesabaran. Hanya menyimpan data yang dicadangkan dalam format yang dapat Anda pulihkan akan menjadi pekerjaan yang signifikan.

Saya setuju dengan jawaban srini.venigalla bahwa menormalkan data seperti orang gila mungkin bukan ide yang baik di sini. Melakukan bergabung di beberapa tabel dengan banyak data akan membuka Anda terhadap risiko jenis file yang bisa berarti beberapa pertanyaan Anda tidak akan pernah kembali. Denormallisasi dengan kunci integer yang sederhana akan memberi Anda peluang sukses yang lebih baik.

Semua yang kami miliki adalah InnoDB. Mengenai MyISAM vs InnoDB: Hal utama adalah untuk tidak mencampur keduanya. Anda tidak dapat benar-benar mengoptimalkan server untuk keduanya karena cara MySQL menyimpan kunci dan data lainnya. Pilih satu atau yang lain untuk semua tabel di server jika Anda bisa. MyISAM dapat membantu dengan beberapa masalah kecepatan, tetapi mungkin tidak membantu dengan pekerjaan DBA keseluruhan yang perlu dilakukan - yang bisa menjadi pembunuh.

Kevin Bedell
sumber
1
MySQL meningkat banyak di departemen indeks (...) sejak 5.0. Akan menarik untuk melihat bagaimana perilakunya sekarang.
Dering Ø
70

normalisasi data seperti orang gila

Normalisasi data seperti orang gila mungkin bukan strategi yang tepat dalam kasus ini. Biarkan opsi Anda tetap terbuka dengan menyimpan data baik dalam bentuk Normalisasi dan juga dalam bentuk tampilan terwujud yang sangat cocok untuk aplikasi Anda. Kunci dalam jenis aplikasi ini BUKAN menulis permintaan adhoc. Pemodelan kueri lebih penting daripada pemodelan data. Mulailah dengan kueri target Anda dan bekerja menuju model data yang optimal.

Is this reasonable?

Saya juga akan membuat tabel datar tambahan dengan semua data.

run_id | spectrum_id | data_id | <data table columns..> |

Saya akan menggunakan tabel ini sebagai sumber utama dari semua kueri. Alasannya adalah untuk menghindari keharusan melakukan penggabungan. Bergabung tanpa pengindeksan akan membuat sistem Anda sangat tidak dapat digunakan, dan memiliki indeks pada file sebesar itu akan sama mengerikannya.

Strategi adalah, kueri terlebih dahulu pada tabel di atas, buang hasilnya ke tabel temp dan gabungkan tabel temp dengan tabel pencarian Run and Spectrum dan dapatkan data yang Anda inginkan.


Sudahkah Anda menganalisis kebutuhan Tulis vs kebutuhan Baca? Akan sangat menggoda untuk membuang SQL dan pergi ke mekanisme penyimpanan data yang tidak standar. Menurut saya, itu harus menjadi pilihan terakhir.

Untuk mempercepat kecepatan penulisan, Anda mungkin ingin mencoba metode Handler Socket. Percona, jika saya ingat, mengemas Socket Handler dalam paket instal mereka. (tidak ada hubungannya dengan Percona!)

http://yoshinorimatsunobu.blogspot.com/2010/10/using-mysql-as-nosql-story-for.html

srini.venigalla
sumber
33

Jawaban singkatnya adalah ya yang memenuhi syarat - karena jumlah baris menumbuhkan skema, tipe data, dan operasi yang Anda pilih semakin penting.

Seberapa banyak Anda menormalkan data Anda tergantung pada operasi yang Anda rencanakan untuk dilakukan pada data yang disimpan. Tabel 'datapoints' Anda khususnya tampaknya bermasalah - apakah Anda berencana membandingkan titik ke-n dari spektrum yang diberikan dengan tanggal yang lain? Jika tidak, menyimpannya secara terpisah bisa menjadi kesalahan. Jika titik data Anda tidak berdiri sendiri tetapi masuk akal hanya dalam konteks spektrum terkait mereka, Anda tidak memerlukan KUNCI UTAMA - kunci asing untuk spektrum dan kolom 'n' (kolom 'indeks' Anda) akan cukup. .

Tentukan operasi inter-dan intra-spektrum yang harus Anda lakukan dan kemudian cari cara termurah untuk mencapainya. Jika hanya diperlukan persamaan, mereka mungkin didenormalisasi - mungkin dengan beberapa metadata statistik pra-kalkulasi yang membantu operasi Anda. Jika Anda benar-benar membutuhkan akses in-SQL ke titik data individual, pastikan Anda mengurangi ukuran setiap baris ke jumlah bidang minimum dan datatype terkecil yang mungkin.

MySQL terbesar yang pernah saya kelola secara pribadi adalah ~ 100 juta baris. Pada ukuran ini Anda ingin menjaga baris Anda dan dengan demikian bidang Anda ukuran tetap - ini memungkinkan MySQL untuk secara efisien menghitung posisi setiap baris dalam tabel dengan mengalikan kali ukuran tetap dari setiap baris (pikirkan aritmatika pointer) - meskipun detail yang tepat tergantung pada mesin penyimpanan yang Anda rencanakan untuk digunakan. Gunakan MyISAM jika Anda dapat melakukannya, kekurangan keandalannya dalam hal kecepatan, dan dalam situasi Anda seharusnya sudah cukup. Ganti bidang ukuran variabel seperti VARCHAR dengan CHAR (n) dan gunakan RTRIM () pada permintaan baca Anda.

Setelah baris tabel Anda memiliki lebar tetap, Anda dapat mengurangi jumlah byte dengan mengevaluasi dengan hati-hati tipe data integer MySQL (beberapa di antaranya non-standar). Setiap penghematan 1-byte yang dapat Anda tambahkan dengan mengubah INT 4-byte menjadi MEDIUMINT 3-byte menghemat Anda ~ 1MB per juta baris - artinya lebih sedikit disk I / O dan caching yang lebih efektif. Gunakan tipe data sekecil mungkin yang bisa Anda dapatkan . Hati-hati mengevaluasi jenis floating point dan lihat apakah Anda dapat mengganti DOUBLE 8-byte dengan FLOAT 4-byte atau bahkan NUMERIK titik tetap <8 byte . Jalankan tes untuk memastikan bahwa apa pun yang Anda pilih tidak menggigit Anda nanti.

Bergantung pada properti yang diharapkan dari dataset Anda dan operasi yang diperlukan mungkin ada penghematan lebih lanjut dalam pengkodean nilai-nilai Anda yang lebih tidak biasa (pola / pengulangan yang diharapkan yang dapat dikodekan sebagai indeks ke dalam serangkaian nilai, data mentah yang mungkin hanya berkontribusi secara bermakna ke metadata dan dibuang, dll) - meskipun optimisasi eksotis, tidak intuitif, destruktif hanya bermanfaat ketika setiap opsi lain telah dicoba.

Yang paling penting, apa pun yang akhirnya Anda lakukan, jangan menganggap Anda telah memilih skema yang sempurna dan kemudian mulai membabi buta 10s jutaan catatan. Desain yang baik membutuhkan waktu untuk berkembang. Buat kumpulan data uji yang besar namun dapat dikelola (katakanlah, 1-5%) dan verifikasi kebenaran dan kinerja skema Anda. Lihat kinerja berbagai operasi (http://dev.mysql.com/doc/refman/5.0/en/using-explain.html) dan pastikan Anda menyeimbangkan skema Anda untuk mendukung operasi yang paling sering.

Apakah saya mengatakan singkat? Aduh. Bagaimanapun, semoga berhasil!

Ryan Flynn
sumber
23

Tampaknya satu-satunya alasan untuk menghancurkan data titik data dari XML (sebagai lawan dari metadata seperti waktu dan jenis run) dan ke dalam bentuk basis data adalah ketika Anda menganalisis spektrum melintasi array - yaitu mungkin menemukan semua berjalan dengan tanda tangan tertentu. Hanya Anda yang tahu domain masalah Anda saat ini, tetapi ini bisa mirip dengan menyimpan sampel musik pada 96kHz dengan 1 sampel per baris. Saya tidak yakin ukuran adalah masalah lebih dari bagaimana data digunakan. Meminta seluruh data akan sama dengan menanyakan amplitudo relatif 2 menit ke dalam lagu di semua lagu oleh The Beatles. Jika Anda tahu jenis analisis yang mungkin dilakukan, sangat mungkin melakukan ini pada sinyal dan menyimpannya dalam metadata tentang proses mungkin lebih masuk akal.

Saya juga tidak yakin apakah data sumber Anda jarang. Sangat mungkin bahwa spektrum dalam database hanya boleh memasukkan entri yang tidak nol, sedangkan XML asli menyertakan entri nol, sehingga jumlah baris Anda bisa jauh lebih sedikit daripada dalam data sumber.

Jadi, seperti banyak pertanyaan, sebelum bertanya tentang MySQL yang menangani model Anda, melangkah mundur dan melihat modelnya dan bagaimana model itu akan digunakan mungkin lebih tepat daripada mengkhawatirkan kinerja dulu.


Setelah meninjau pembaruan pertanyaan Anda, saya pikir model di mana data biner disimpan sebagai BLOB atau hanya sebuah pointer ke file sudah cukup dan bekerja pada memodifikasi model Anda untuk menyimpan data tentang puncak signifikan yang telah diidentifikasi ketika data pertama kali Baca.

Cade Roux
sumber
18

Saya menjalankan layanan analisis web dengan sekitar 50 server basis data, masing-masing berisi banyak tabel lebih dari 100 juta baris, dan beberapa yang cenderung lebih dari satu miliar baris, terkadang hingga dua miliar (pada setiap server).

Performa di sini baik-baik saja. Ini adalah data yang sangat normal. Namun - perhatian utama saya dengan membaca ini adalah bahwa Anda akan lebih dari 4,2 miliar tanda baris untuk tabel ini (mungkin bukan "berjalan" tetapi mungkin dua lainnya), yang berarti Anda harus menggunakan BIGINT daripada INT untuk kunci utama / asing.

Kinerja MySQL dengan bidang BIGINT dalam kolom yang diindeks sangat mengerikan dibandingkan dengan INT. Saya membuat kesalahan dengan melakukan hal ini sekali dengan meja yang saya pikir akan tumbuh melebihi ukuran ini, dan begitu mencapai beberapa ratus juta baris, performanya sangat buruk. Saya tidak memiliki angka mentah tetapi ketika saya mengatakan buruk, maksud saya Windows ME buruk.

Kolom ini adalah kunci utama. Kami mengubahnya kembali menjadi hanya INT dan presto magico, kinerjanya bagus lagi.

Semua server kami pada saat itu menggunakan Debian 5 dan dengan MySQL 5.0. Kami telah meningkatkan ke Debian 6 dan Percona MySQL 5.5, jadi hal-hal mungkin telah membaik sejak saat itu. Tetapi berdasarkan pengalaman saya di sini, tidak, saya tidak berpikir itu akan bekerja dengan baik.

Sean
sumber
17

Apakah itu berfungsi atau tidak, Anda akan selalu mengalami masalah yang sama dengan media penyimpanan tunggal monolitik: disk lambat. Pada 100 MB / s (cukup bagus untuk media pemintalan) dibutuhkan 3 jam hanya untuk membaca tabel 1TB; itu dengan asumsi tidak ada analisis atau pencarian atau penundaan lain memperlambat Anda.

Inilah sebabnya mengapa hampir setiap instalasi "data besar" menggunakan semacam penyimpanan data terdistribusi. Anda dapat menghabiskan 8 kali lebih banyak uang untuk membangun satu komputer super luar biasa untuk menjalankan DB, tetapi jika Anda memiliki banyak data yang dapat dipindai secara paralel, Anda hampir selalu lebih baik mendistribusikan beban di 8 komputer yang lebih murah.

Proyek seperti hadoop dibangun khusus untuk tujuan seperti ini. Anda membangun sekelompok komputer murah, mendistribusikan data di semua dari mereka, dan permintaan mereka secara paralel. Ini hanya salah satu dari setengah solusi yang dibangun berdasarkan ide yang sama, tetapi ini adalah solusi yang sangat populer.

tylerl
sumber
13

Hm ... Saya melihat dua alasan mengapa Anda memilih jenis struktur data ini:

  • Anda benar-benar perlu melakukan datapoint vs kueri datapoint
  • Anda berniat untuk melakukan semua logika Anda dalam SQL

Sekarang, saya akan menyarankan untuk memeriksa persyaratan Anda dan memverifikasi bahwa setidaknya satu dari asumsi di atas benar. Jika tidak ada yang benar, Anda hanya membuat segalanya lebih lambat. Untuk jenis dataset ini, saya akan menyarankan terlebih dahulu mencari tahu bagaimana data diharapkan akan diakses, akurasi seperti apa yang Anda butuhkan, dll - dan kemudian desain database Anda di sekitar itu.

PS: Perlu diingat bahwa Anda akan membutuhkan setidaknya 36 + 5 byte per titik data, jadi dengan titik data 200B yang seharusnya memberi Anda setidaknya 8,2 TB ruang yang dibutuhkan.

PPS: Anda tidak perlu idkolom pada datapointstabel, PRIMARY KEY (spectrum_id, index)mungkin sudah mencukupi (hanya waspada yang indexmungkin kata yang dilindungi undang-undang)


sumber
12

SUNTING:

JANGAN MELAKUKAN INI DI MYSQL DENGAN DATA YANG DISIMPAN PADA TUNGGAL TUNGGAL. Hanya membaca bahwa jumlah data dari satu media akan memakan waktu berjam-jam. Anda perlu SKALA KELUAR, BUKAN ATAS.

Dan Anda perlu mendenormalisasi data Anda jika Anda ingin melakukan analisis data yang efektif. Anda tidak merancang sistem online di sini. Anda ingin mengolah angka, desain yang sesuai.

Jawaban asli di bawah baris.


Jawabannya akan bervariasi tergantung pada pertanyaan Anda, MySQL mungkin bukan alat terbaik untuk pekerjaan ini. Anda mungkin ingin melihat solusi yang dapat Anda skala "keluar" dan tidak "naik". Jika Anda bersedia melakukan upaya mungkin Anda harus melihat pada solusi Mengurangi Peta seperti Hadoop.

Jika Anda ingin melakukan lebih banyak permintaan ad-hoc , solusi BigQuery Google mungkin cocok untuk Anda. Presentasi yang relevan dari Google I / O 2012: Memecah Data Besar dengan BigQuery

Jadi, solusinya akan tergantung pada apakah ini adalah hal satu-shot dan jika Anda ingin cukup mendukung permintaan ad hoc.

mdolk
sumber
9

Tidak ada yang menyebutkan, jadi saran saya. Lihatlah solusi MySQL yang terbengkalai secara besar-besaran . Misalnya, lihat presentasi tumblr yang sangat dihormati ini .

Konsepnya adalah:

  • Alih-alih satu database ekstra besar
  • Gunakan banyak yang kecil yang memegang bagian dari data asli

Dengan demikian Anda dapat mengatur skala secara horizontal, alih-alih mencoba meningkatkan kinerja vertikal. Google BigTable dan GFS juga menggunakan node yang dapat diskalakan secara horizontal untuk menyimpan dan meminta petabyte data.

Namun, akan ada masalah jika Anda perlu menjalankan kueri di atas pecahan yang berbeda.


Jika ada yang tertarik, saya membuat aplikasi sharding hello-world beberapa waktu lalu. Itu dibahas di sini di posting blog. Saya menggunakan RavenDB dan C # tetapi detailnya tidak relevan dan idenya sama.

oleksii
sumber
7

Mesin seperti apa data akan disimpan? Apakah ini perangkat penyimpanan bersama?

Faktor utama yang akan menentukan waktu permintaan Anda akan menjadi perangkat keras Anda. Database dan pengoptimal kueri mereka dirancang untuk mengurangi jumlah disk I / Os sebanyak mungkin. Mengingat Anda hanya memiliki 3 tabel, ini akan dilakukan dengan cukup andal.

Kecepatan baca / tulis harddisk akan 200-300 kali lebih lambat daripada kecepatan memori. Cari perangkat keras dengan latensi yang sangat cepat dan kecepatan baca dan tulis yang cepat. Jika semua data ini dalam satu drive 2-TB, Anda mungkin akan menunggu waktu yang lama untuk menyelesaikan pertanyaan. Harddrive latency adalah ~ 10-15milliseconds sedangkan latency memori kurang dari 10nanoseconds. Harddrive latency bisa 1000-2000x lebih lambat dari latensi memori. Pergerakan lengan mekanis pada harddisk adalah yang TERLambat dalam keseluruhan sistem ini.

Berapa banyak RAM yang Anda miliki? 16GB? Katakanlah yang memungkinkan Anda memegang 32 catatan. Anda memiliki 16000 file. Jika Anda akan memindai linear semua titik data, Anda dapat dengan mudah berakhir dengan 5-10 detik untuk mencari waktu sendirian. Lalu faktor dalam transfer rate 50mb / s? Sekitar 7 jam. Selain itu, setiap data yang disimpan sementara harus disimpan pada harddirve untuk memberikan ruang bagi data baru yang sedang dibaca.

Jika Anda menggunakan perangkat penyimpanan bersama yang digunakan secara aktif oleh pengguna lain ... taruhan terbaik Anda akan menjalankan semuanya pada malam hari.

Mengurangi jumlah kueri bersarang juga membantu. Kueri bersarang menghasilkan tabel sementara yang akan merambah hard drive Anda lebih banyak lagi. Saya harap Anda memiliki banyak ruang kosong di harddisk Anda.

Optimasi kueri hanya dapat melihat 1 kueri sekaligus. Jadi pilih pernyataan bersarang tidak dapat dioptimalkan. NAMUN, jika Anda tahu permintaan bersarang tertentu akan menghasilkan set data kecil untuk dikembalikan, simpanlah. Optimasi kueri menggunakan histogram dan asumsi kasar, jika Anda mengetahui sesuatu tentang data dan kueri, silakan dan lakukan.

Semakin banyak Anda tahu tentang cara data Anda disimpan di disk, semakin cepat Anda dapat menulis pertanyaan Anda. Jika semuanya disimpan secara berurutan pada kunci utama, mungkin bermanfaat untuk mengurutkan kunci primer yang dikembalikan dari kueri bersarang. Juga, jika Anda dapat mengurangi set kumpulan data yang perlu Anda analisis sama sekali sebelumnya, lakukanlah. Tergantung pada sistem Anda, Anda melihat sekitar 1 detik transfer data per file.

Jika Anda akan memodifikasi nilai Name (varchars) saya akan mengubahnya ke tipe data dengan ukuran maksimum, itu akan mencegah fragmentasi dan trade off hanya beberapa byte memori. Mungkin NVARCHAR dengan maksimum 100.

Sejauh komentar tentang denormalisasi tabel. Saya pikir mungkin yang terbaik untuk hanya menyimpan datapoints dalam kelompok yang lebih besar (mungkin sebagai spektra) dan kemudian melakukan analisis data dalam python atau bahasa yang berinteraksi dengan database. Kecuali Anda seorang SQL-Wizard.

JustinDanielson
sumber
3
Anda menekankan perbedaan besar dalam hard drive vs latensi memori tetapi angka Anda dimatikan oleh faktor 1000. Jika hard drive memiliki latensi sekitar 10ms, dan memori 10ns, latensi tidak berbeda dengan faktor 1.000 tetapi faktor dari 1.000.000!
spectre256
6

Bagi saya itu terdengar seperti skenario penggunaan di mana Anda menginginkan sesuatu seperti "toko kolom relasional" seperti yang dijelaskan di sini .

Saya mungkin salah memahami desain, tetapi jika Anda terutama berurusan dengan koleksi array yang besar, menyimpannya dalam tabel berorientasi baris yang khas berarti bahwa setiap elemen mirip dengan slice. Jika Anda tertarik untuk melihat irisan dengan cara yang khas, itu masuk akal, tetapi bisa jadi kurang efisien jika Anda benar-benar melihat seluruh kolom sekaligus.

Saat mengambil array, tidak hanya Anda mungkin tidak perlu bergabung dengan tabel lain yang dihasilkan dari normalisasi Anda, tetapi Anda dapat mengambil seri sebagai array daripada hash.

Saya mungkin benar-benar salah paham masalah, dan saya bahkan tidak menyarankan solusi spesifik.

Berikut ini pembicaraan lain yang mungkin relevan, bahkan jika itu bukan solusi saat ini atau yang bisa digunakan.

RandallZ
sumber
6

Saya sarankan Anda mencoba dan mempartisi meja Anda. Kami memiliki lebih dari 80 juta baris dalam satu tabel (data pasar saham) dan tidak mengalami kesulitan mengaksesnya dengan cepat.

Bergantung pada bagaimana Anda bermaksud mencari data Anda, Anda harus mendesain partisi Anda. Dalam kasus kami menurut tanggal berfungsi dengan baik karena kami meminta tanggal tertentu.

http://dev.mysql.com/doc/refman/5.1/en/partitioning-limitations.html

http://www.slideshare.net/datacharmer/mysql-partitions-tutorial

pengguna9866
sumber
5

Ya tapi...

Saya telah bekerja dengan tabel yang memiliki 2 milyar baris. Namun hanya pertanyaan yang menggunakan PK diharapkan cepat.

Yang paling penting, perangkat keras memiliki RAM yang cukup untuk memenuhi seluruh tabel dalam memori. Ketika itu menjadi masalah (maks. Pada 96GB pada waktu itu), pergi untuk partisi vertikal, menjaga ukuran meja diatur pada setiap mesin cukup kecil untuk tetap muat di memori. Juga, mesin-mesin itu terhubung melalui serat 10Gb, jadi throughput jaringan tidak terlalu menjadi masalah.

BTW. skema Anda terlihat seperti sesuatu, yang bisa masuk ke dalam solusi NoSQL, menggunakan run_idkunci hashing untuk spektra dan spectrum_idsebagai kunci hashing untuk titik data.

vartec
sumber
4

Saya telah menulis tentang topik ini di blog saya: http://www.tocker.ca/2013/10/24/improving-the-performance-of-large-tables-in-MySQL.html

Untuk mengulangi beberapa poin utama:

  • Pohon-B menurun karena semakin besar dan tidak muat ke dalam memori (MySQL tidak sendirian di sini).
  • InnoDB memang memiliki beberapa fitur untuk membantu mempertahankan beberapa kinerja (ubah buffering; sebelumnya disebut 'insert buffer').
  • Partisi juga dapat membantu.

Dalam komentar di pos saya, Tim Callaghan menautkan ini: http://www.tokutek.com/resources/benchmark-results/benchmarks-vs-innodb-hdds/#iiBench

Yang menunjukkan memasukkan 1 Miliar baris menggunakan tolok ukur iibench.

Morgan Tocker
sumber