Pendekatan terbaik untuk memecah tabel MySQL adalah tidak melakukannya kecuali benar-benar tidak dapat dihindari untuk melakukannya.
Saat Anda menulis aplikasi, Anda biasanya ingin melakukannya dengan cara yang memaksimalkan kecepatan, kecepatan pengembang. Anda mengoptimalkan latensi (waktu hingga jawaban siap) atau throughput (jumlah jawaban per unit waktu) hanya jika diperlukan.
Anda mempartisi dan kemudian menetapkan partisi ke host yang berbeda (= shard) hanya jika jumlah dari semua partisi ini tidak lagi sesuai dengan satu instance server database - alasannya adalah untuk menulis atau membaca.
Kasus penulisan adalah a) frekuensi penulisan membebani disk server ini secara permanen atau b) ada terlalu banyak penulisan yang terjadi sehingga replikasi secara permanen tertinggal dalam hierarki replikasi ini.
Kasus pembacaan untuk sharding adalah saat ukuran datanya begitu besar sehingga kumpulan yang berfungsi tidak lagi cocok dengan memori dan pembacaan data mulai mengenai disk alih-alih disajikan dari memori sebagian besar waktu.
Hanya ketika Anda harus memecah Anda melakukannya.
Saat Anda memecah, Anda membayarnya dengan berbagai cara:
Sebagian besar SQL Anda tidak lagi bersifat deklaratif.
Biasanya, dalam SQL Anda memberi tahu database data apa yang Anda inginkan dan menyerahkannya kepada pengoptimal untuk mengubah spesifikasi itu menjadi program akses data. Itu bagus, karena fleksibel, dan karena menulis program akses data ini adalah pekerjaan membosankan yang merusak kecepatan.
Dengan lingkungan sharded Anda mungkin menggabungkan tabel pada node A terhadap data pada node B, atau Anda memiliki tabel yang lebih besar dari node, pada node A dan B dan menggabungkan data darinya terhadap data yang ada di node B dan C. Anda mulai menulis resolusi gabungan berbasis hash sisi aplikasi secara manual untuk menyelesaikannya (atau Anda menciptakan kembali kluster MySQL), yang berarti Anda berakhir dengan banyak SQL yang tidak lagi deklaratif, tetapi mengekspresikan fungsionalitas SQL secara prosedural (misalnya Anda menggunakan pernyataan SELECT dalam loop).
Anda mengalami banyak latensi jaringan.
Biasanya, kueri SQL dapat diselesaikan secara lokal dan pengoptimal mengetahui tentang biaya yang terkait dengan akses disk lokal dan menyelesaikan kueri dengan cara yang meminimalkan biaya untuk itu.
Dalam lingkungan yang dipecah, kueri diselesaikan dengan menjalankan akses nilai kunci di seluruh jaringan ke beberapa node (mudah-mudahan dengan akses kunci bertumpuk dan bukan pencarian kunci individu per perjalanan) atau dengan mendorong bagian WHERE
klausa ke node di mana mereka bisa. diterapkan (yang disebut 'kondisi pushdown'), atau keduanya.
Tetapi bahkan dalam kasus terbaik ini melibatkan lebih banyak perjalanan pulang pergi jaringan daripada situasi lokal, dan ini lebih rumit. Terutama karena pengoptimal MySQL sama sekali tidak tahu tentang latensi jaringan (Ok, cluster MySQL perlahan menjadi lebih baik dalam hal itu, tetapi untuk vanilla MySQL di luar cluster itu masih berlaku).
Anda kehilangan banyak kekuatan ekspresif dari SQL.
Oke, itu mungkin kurang penting, tetapi batasan kunci asing dan mekanisme SQL lainnya untuk integritas data tidak dapat mencakup beberapa pecahan.
MySQL tidak memiliki API yang memungkinkan kueri asinkron yang berfungsi dengan baik.
Ketika data dengan tipe yang sama berada di beberapa node (misalnya data pengguna pada node A, B dan C), pertanyaan horizontal sering kali perlu diselesaikan terhadap semua node ini ("Temukan semua akun pengguna yang belum masuk selama 90 hari atau lebih"). Waktu akses data tumbuh secara linier dengan jumlah node, kecuali beberapa node dapat diminta secara paralel dan hasilnya dikumpulkan saat mereka masuk ("Map-Reduce").
Prasyarat untuk itu adalah API komunikasi asinkron, yang tidak ada untuk MySQL dalam bentuk kerja yang baik. Alternatifnya adalah banyak percabangan dan koneksi dalam proses anak, yang mengunjungi dunia mengisap tiket masuk musim.
Setelah Anda memulai sharding, struktur data dan topologi jaringan menjadi terlihat sebagai poin kinerja untuk aplikasi Anda. Untuk berkinerja cukup baik, aplikasi Anda perlu menyadari hal-hal ini, dan itu berarti hanya sharding level aplikasi yang masuk akal.
Pertanyaannya lebih lanjut jika Anda ingin melakukan pecahan otomatis (menentukan baris mana yang masuk ke node mana dengan mencirikan kunci utama misalnya) atau jika Anda ingin memisahkan secara fungsional dengan cara manual ("Tabel yang terkait dengan cerita pengguna xyz masuk ke sini master, sedangkan tabel terkait abc dan def pergi ke master itu ").
Sharding fungsional memiliki keuntungan yang, jika dilakukan dengan benar, tidak akan terlihat oleh sebagian besar pengembang di sebagian besar waktu, karena semua tabel yang terkait dengan kisah pengguna mereka akan tersedia secara lokal. Hal ini memungkinkan mereka untuk tetap mendapatkan keuntungan dari SQL deklaratif selama mungkin, dan juga akan menimbulkan latensi jaringan yang lebih sedikit karena jumlah transfer lintas jaringan dijaga agar tetap minimal.
Sharding fungsional memiliki kelemahan yaitu tidak memungkinkan tabel tunggal lebih besar dari satu instans, dan memerlukan perhatian manual dari seorang desainer.
Keunggulan sharding fungsional adalah relatif mudah dilakukan pada basis kode yang sudah ada dengan jumlah perubahan yang tidak terlalu besar. http://Booking.com telah melakukannya beberapa kali dalam beberapa tahun terakhir dan berhasil dengan baik untuk mereka.
Setelah mengatakan semua itu, melihat pertanyaan Anda, saya yakin Anda mengajukan pertanyaan yang salah, atau saya benar-benar salah memahami pernyataan masalah Anda.