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.
Aplikasi Level sharding: dbShards adalah satu-satunya produk yang saya tahu yang melakukan "application aware sharding". Ada beberapa artikel bagus di situs web. Secara definisi, sharding yang sadar aplikasi akan lebih efisien. Jika aplikasi tahu persis ke mana harus pergi dengan transaksi tanpa harus mencarinya atau dialihkan oleh proxy, itu sendiri akan lebih cepat. Dan kecepatan sering kali menjadi salah satu perhatian utama, jika bukan satu-satunya perhatian, ketika seseorang mencari sharding.
Beberapa orang "memecah" dengan proxy, tetapi di mata saya itu mengalahkan tujuan dari pecahan. Anda hanya menggunakan server lain untuk memberi tahu transaksi Anda di mana menemukan data atau di mana menyimpannya. Dengan sharding yang sadar aplikasi, aplikasi Anda tahu ke mana harus pergi sendiri. Jauh lebih hemat.
Ini sama dengan # 2 sebenarnya.
sumber
Beberapa proyek baru di ruang ini:
github.com/twitter/gizzard/sumber
Shard-Query adalah solusi sharding berbasis OLAP untuk MySQL. Ini memungkinkan Anda untuk menentukan kombinasi tabel dengan sharded dan tabel tanpa shard. Tabel yang tidak dipisahkan (seperti tabel pencarian) dapat digabungkan secara bebas ke tabel yang dipisahkan, dan tabel yang dipisahkan dapat digabungkan satu sama lain selama tabel tersebut digabungkan dengan kunci beling (tidak ada pecahan silang atau penggabungan mandiri yang melintasi batas pecahan). Sebagai solusi OLAP, Shard-Query biasanya memiliki waktu respons minimum 100 md atau kurang, bahkan untuk kueri sederhana sehingga tidak akan berfungsi untuk OLTP. Shard-Query dirancang untuk menganalisis kumpulan data besar secara paralel.
Solusi sharding OLTP juga tersedia untuk MySQL. Solusi sumber tertutup termasuk ScaleDB , DBShards . Solusi OLTP open source termasuk JetPants , Cubrid atau Flock / Gizzard (infrastruktur Twitter).
sumber
Tingkat aplikasi tentu saja.
Pendekatan terbaik yang pernah saya temukan dalam buku ini
MySQL Kinerja Tinggi http://www.amazon.com/High-Performance-MySQL-Jeremy-Zawodny/dp/0596003064
Deskripsi singkat: Anda dapat membagi data Anda menjadi banyak bagian dan menyimpan ~ 50 bagian di setiap server. Ini akan membantu Anda menghindari masalah terbesar kedua dari sharding - penyeimbangan ulang. Pindahkan saja beberapa di antaranya ke server baru dan semuanya akan baik-baik saja :)
Saya sangat menyarankan Anda untuk membelinya dan membaca bagian "skala mysql".
sumber
Pada 2018, tampaknya ada solusi asli MySql untuk itu. Sebenarnya ada setidaknya 2 - InnoDB Cluster dan NDB Cluster (ada versi komersial dan komunitasnya).
Karena kebanyakan orang yang menggunakan edisi komunitas MySql lebih akrab dengan mesin InnoDB, inilah yang harus dieksplorasi sebagai prioritas pertama. Ini mendukung replikasi dan partisi / sharding out of the box dan didasarkan pada MySql Router untuk berbagai opsi perutean / load-balancing.
Sintaks untuk pembuatan tabel Anda perlu diubah, misalnya:
CREATE TABLE t1 (col1 INT, col2 CHAR(5), col3 DATETIME) PARTITION BY HASH ( YEAR(col3) );
(ini hanya satu dari empat jenis partisi )
Satu batasan yang sangat penting:
sumber
PARTITION BY HASH(YEAR...)
akan memindai semua partisi jika Anda memiliki rentang tanggal. Yuck.