Tabel Pemisahan di MySQL. Latihan yang bagus?

14

Saya sudah mulai mengerjakan proyek yang sudah ada dan pengembang sebelumnya telah membagi tabel menjadi 10 tabel terpisah dengan skema identik tetapi data berbeda.

Tabelnya terlihat seperti ini:

[tableName_0]
[tableName_1]
[tableName_2]
[tableName_3]
[tableName_4]
[tableName_5]
[tableName_6]
[tableName_7]
[tableName_8]
[tableName_9]

Kunci utama adalah idbidang bilangan bulat . Aplikasi ini menggunakan algoritma hash ( idmod 10) untuk mengetahui tabel apa yang harus diakses ketika melakukan pencarian. Misalnya id= 10 akan menghasilkan [tableName_0].

Digabungkan, tabel mungkin memiliki 100.000 baris dan tingkat pertumbuhan relatif rendah.

Jadi, pertanyaan saya adalah apakah ini solusi yang layak atau bahkan jika itu adalah praktik yang baik dalam situasi apa pun. Teori saya adalah mendorong agar mereka digabungkan karena akan membuat segalanya lebih mudah sejauh UNIONs, dll. Kelemahan utama adalah mengubah semua kode aplikasi dan apakah itu layak untuk jangka panjang.

PinkGrapefruit
sumber

Jawaban:

16

Saya pikir semua orang terlalu rumit. Poin kuncinya di sini adalah:

Digabungkan, tabel mungkin memiliki 100.000 baris dan tingkat pertumbuhan relatif rendah.

Ini adalah sepotong kue untuk ditangani RDBMS. Pergi dengan satu tabel, indeks dengan benar, dan menganggapnya sebagai masalah terpecahkan.

Anda tidak perlu mempertimbangkan untuk mempartisi, baik "buatan sendiri" atau lainnya, sampai Anda mulai menangani volume data yang sangat besar - pikirkan miliaran baris ke atas.

Nick Chammas
sumber
3

Anda bisa menggunakan tabel gabungan, namun mereka lebih kuno dari versi 4.x. Mengingat aplikasi Anda dipartisi secara manual karena a) Anda menjalankan versi yang sangat lama atau b) pengembang asli tidak mengetahui partisi tabel.

Singkatnya jika Anda menjalankan 5.1+, Anda dapat membiarkan mysql melakukan partisi ini untuk Anda. Lihat http://dev.mysql.com/doc/refman/5.1/en/partitioning.html Jika Anda menggunakan 5.5 Anda harus memeriksa dokumen spesifik tersebut karena Anda akan menemukan beberapa perbedaan.

Ada banyak keuntungan untuk mempartisi. Namun itu benar-benar tergantung pada dataset yang ada, pola akses dan bagaimana cara diindeks. Juga, perlu diingat komentar saya berikut ini dalam konteks partisi mysql 5+, BUKAN tabel mysql Merge yang lebih lama; meskipun kadang-kadang dibahas dalam hal partisi.

Beberapa contoh:

  • Bucket lurus (atau hashing) berdasarkan kunci pencarian yang sering diakses. Jika Anda cukup sering mencari dengan kunci utama atau unik lainnya maka mysql dapat memotong ruang pencarian dengan faktor berapa banyak partisi yang Anda miliki. Namun perlu dicatat bahwa hal ini dapat merugikan jika Anda mempartisi dengan satu kunci dan kemudian sering mencari dengan kunci lain. Jika Anda mencari dengan kunci data tidak dipartisi maka itu harus melakukan pencarian LEBIH BANYAK pada pencarian (satu untuk setiap partisi, b / c terus terang, itu tidak tahu di mana data itu)
  • Pertimbangkan situasi jika Anda memiliki serangkaian catatan temporal yang tumbuh berdasarkan tanggal dan Anda secara berkala memangkas bulan sebelumnya. Jika Anda mempartisi berdasarkan tanggal maka Anda cukup menjatuhkan partisi yang sama cepatnya dengan menjatuhkan tabel, tidak peduli seberapa besar. Jika Anda harus memangkas tabel seperti itu berdasarkan tanggal, Anda harus mengeluarkan satu atau lebih DELETE kueri di mana setiap baris dihapus. Kelemahan dari ini adalah mysql tidak secara otomatis membuat partisi baru setelah Anda mencapai tanggal maksimum yang Anda perhitungkan dalam skenario ini; Anda memerlukan skrip pemeliharaan tambahan yang dibangun di bagian Anda untuk menambahkan partisi sesuai kebutuhan.
  • Jika Anda menggunakan myisam, pemeriksaan dan pemulihan jauh lebih cepat. Pertimbangkan tabel myisam 100G. Jika Anda ingin memulihkan tabel yang macet, Anda setidaknya membutuhkan sekitar 100G ruang disk cadangan. Jika dipartisi menjadi 10 potongan berbeda dengan ukuran yang sama maka Anda hanya perlu 10G ruang (dan kurang memori key_sort_buffer untuk pemulihan cepat); tetapi perlu melakukan iterasi untuk setiap partisi.

Jadi secara ringkas, pendekatan umum tabel partisi dapat menawarkan banyak manfaat. Namun itu bukan peluru ajaib untuk diterapkan secara membabi buta tanpa pertimbangan untuk mengakses pola dan bagaimana tepatnya Anda mempartisi.

Saya bisa membayangkan situasi di mana partisi yang diinginkan sangat spesifik untuk aplikasi dan akan lebih cocok untuk menempatkan logika di lapisan aplikasi. Namun mengingat deskripsi modulus langsung Anda ini tidak tampak seperti kasus seperti itu.

EDIT

Dalam menulis deskripsi saya, saya lupa bahwa Anda menyatakan meja Anda adalah 100 ribu baris. Tanpa skema penuh dari meja Anda dan panjang baris rata-rata sulit dikatakan, tetapi secara umum itu terdengar berukuran sedang bahkan untuk perangkat keras sederhana. Pada saat yang sama, jika tidak menyebabkan masalah seperti sekarang atau di masa mendatang maka jangan menghabiskan waktu dan memperkenalkan risiko dengan mengubahnya.

atxdba
sumber
3

Apa yang telah dilakukan pengembang sebelumnya untuk Anda adalah membangun implementasi partisi-by-hash mereka sendiri. MySQL secara harfiah mendukung ini secara asli dari MySQL 5.1:

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

Saya tidak bisa memikirkan alasan yang bagus jadi terapkan partisi-by-hash Anda sendiri daripada mengandalkan versi asli [1]. Melakukan perubahan skema akan menjadi mimpi buruk.

Saya juga jarang merekomendasikan partisi-by-hash (implementasi asli). Saya pikir itu akan berguna jika Anda bisa menggunakannya untuk mencari paralel setiap partisi sekaligus (yang tidak akan dilakukan MySQL). Jika Anda perlu mencari di beberapa partisi, skema yang Anda jelaskan akan jauh lebih lambat.

[1] Namun, untuk beberapa tipe partisi lainnya, masuk akal untuk menggulir partisi Anda sendiri. MySQL memaksa Anda untuk membuat kunci partisi Anda bagian dari kunci utama Anda dan semua indeks unik.

Morgan Tocker
sumber
2

Menanggapi pertanyaan:

apakah ini merupakan solusi yang layak atau tidak

IMHO, Ini sepertinya overhead yang tidak perlu. Anda cukup mengindeks dan mempartisi satu tabel dengan benar kecuali ada beberapa informasi lain yang tidak diungkapkan dalam deskripsi.

Menanggapi pertanyaan:

... jika itu praktik yang baik dalam situasi apa pun

IMHO, sharding vertikal bisa masuk akal tergantung pada konteksnya. Ketika saya melihat ini, biasanya dalam semacam bentuk log. Mari kita berpura-pura kita menggunakan ini untuk log server web dan kami ingin mempartisi berdasarkan bulan. Alih-alih mengubah tabel yang ada di tempatnya setiap hari, kita bisa membuat tabel baru setiap hari dan mencatat baris ke tabel itu.

mis. Berpura-pura tabel log web mungkin berbentuk:

datetime TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
uri VARCHAR(1024),
host VARCHAR(255),
user_agent VARCHAR(255),
etc...

Solusi Anda membuat tabel sesuai kebutuhan dalam database weblog:

weblogs.20120301
weblogs.20120302
weblogs.20120303

dll.

Dengan cara ini, data tetap dapat dipelihara dan dicari. Ekstraksi menjadi proses periodik yang normal. Operasi berkelanjutan tidak dikunci oleh operasi pada data yang lebih lama.

Dalam skenario yang Anda sajikan, Anda terkunci ke dalam struktur, jadi mengapa tidak menggunakan tabel tunggal yang dioptimalkan untuk tujuan ini? Algoritma penyimpanan penyimpanan baris tampaknya samar dan rentan kesalahan.

randomx
sumber
0

Jika kueri menargetkan data yang sangat besar, pemisahan data menurut kondisi kueri akan memiliki peningkatan kinerja yang luar biasa. Tapi perpecahan seperti itu, seperti yang Anda lihat, membawa beberapa masalah pemrograman.

Jadi pertanyaannya adalah: Apakah nilai split untuk kinerja, atau itu merusak kinerja?

Jika Anda memiliki transaksi yang perlu mengunci beberapa baris pada beberapa tabel dan ada masalah di dalamnya (misalnya, kebuntuan atau batas waktu transaksi), Anda mungkin ingin menggabungkannya ke dalam satu tabel dan menulis ulang SQL untuk memperbaiki masalah.

Ketika saya berpikir tentang apakah akan membagi tabel, saya biasanya mempertimbangkan trade-off antara peningkatan kinerja dan kompleksitas pemrograman.

Dalam situasi Anda, modifikasi kode yang ada mungkin merupakan solusi jangka panjang untuk membuat kode lebih mudah dipelihara. Saya akan menyarankan mencoba meta-programming. Misalnya, menggunakan StringTemplate untuk menghasilkan SQL secara dinamis. Saya suka menghasilkan SQL dari mesin meta-pemrograman jika modifikasi kode yang ada terlalu sulit.

Mike Lue
sumber
0

Saat Anda perlu menyimpan file dalam tabel, menggunakan metodologi ini membantu mengekspor, memperbaiki, dan memulihkan.

Saya memiliki tabel dengan> 30 Gb yang dipartisi dalam 10 tabel. Tabel ini hanya memiliki ID - BLOB dan bagi saya mudah untuk menyimpannya. Dan saya menggunakan MyISAM untuk menyimpan buffer INNODB.

Marcelo Bus
sumber