Sebagian besar database tumbuh dalam ukuran dari waktu ke waktu. Pertumbuhan tidak selalu cukup cepat untuk mempengaruhi kinerja database, tetapi pasti ada kasus di mana itu terjadi. Ketika itu terjadi, kita sering bertanya-tanya apa yang bisa dilakukan untuk mengurangi dampak tersebut dan bagaimana kita bisa memastikan operasi database yang lancar saat menangani data dalam skala besar.
Pertama-tama, mari kita coba mendefinisikan apa yang dimaksud dengan "volume data besar"? Untuk MySQL atau MariaDB, InnoDB tidak terkompresi. InnoDB bekerja sedemikian rupa sehingga sangat diuntungkan dari memori yang tersedia - terutama kumpulan buffer InnoDB. Selama data cocok di sana, akses disk diminimalkan untuk menangani penulisan saja - pembacaan disajikan di luar memori. Apa yang terjadi ketika data melebihi memori? Semakin banyak data yang harus dibaca dari disk ketika ada kebutuhan untuk mengakses baris, yang saat ini tidak di-cache. Ketika jumlah data meningkat, beban kerja beralih dari terikat CPU ke terikat I/O. Ini berarti bahwa kemacetan bukan lagi CPU (yang terjadi ketika data masuk ke memori - akses data dalam memori cepat, transformasi dan agregasi data lebih lambat) melainkan subsistem I/O (operasi CPU pada data jauh lebih cepat daripada mengakses data dari disk.) Dengan peningkatan adopsi flash, beban kerja terikat I/O tidak terlalu buruk seperti dulu pada saat hard disk berputar (akses acak jauh lebih cepat dengan SSD) tetapi kinerja tetap ada .
Hal lain yang harus kita ingat bahwa kita biasanya hanya peduli dengan dataset aktif. Tentu, Anda mungkin memiliki terabyte data dalam skema Anda, tetapi jika Anda hanya mengakses 5GB terakhir, ini sebenarnya situasi yang cukup bagus. Tentu, ini masih menimbulkan tantangan operasional, tetapi dari segi kinerja seharusnya masih baik-baik saja.
Mari kita asumsikan untuk tujuan blog ini, dan ini bukan definisi ilmiah, bahwa dengan volume data yang besar yang kami maksud adalah kasus di mana ukuran data aktif secara signifikan melebihi ukuran memori. Ini bisa menjadi 100GB ketika Anda memiliki memori 2GB, dapat menjadi 20TB ketika Anda memiliki memori 200GB. Titik kritisnya adalah beban kerja Anda terikat dengan I/O secara ketat. Bersabarlah bersama kami saat kami membahas beberapa opsi yang tersedia untuk MySQL dan MariaDB.
Mempartisi
Pendekatan historis (tetapi sangat valid) untuk menangani volume data yang besar adalah dengan mengimplementasikan partisi. Ide di baliknya adalah untuk membagi tabel menjadi beberapa partisi, semacam sub-tabel. Perpecahan terjadi sesuai dengan aturan yang ditentukan oleh pengguna. Mari kita lihat beberapa contohnya (contoh SQL diambil dari dokumentasi MySQL 8.0)
MySQL 8.0 hadir dengan jenis partisi berikut:
- BERBAGAI
- DAFTAR
- KOLOM
- HASH
- KUNCI
Itu juga dapat membuat subpartisi. Kami tidak akan menulis ulang dokumentasi di sini tetapi kami masih ingin memberi Anda beberapa wawasan tentang cara kerja partisi. Untuk membuat partisi, Anda harus menentukan kunci partisi. Ini bisa berupa kolom atau dalam kasus RANGE atau LIST beberapa kolom yang akan digunakan untuk menentukan bagaimana data harus dipecah menjadi beberapa partisi.
Partisi HASH mengharuskan pengguna untuk menentukan kolom, yang akan di-hash. Kemudian, data akan dibagi menjadi sejumlah partisi yang ditentukan pengguna berdasarkan nilai hash tersebut:
CREATE TABLE employees (
id INT NOT NULL,
fname VARCHAR(30),
lname VARCHAR(30),
hired DATE NOT NULL DEFAULT '1970-01-01',
separated DATE NOT NULL DEFAULT '9999-12-31',
job_code INT,
store_id INT
)
PARTITION BY HASH( YEAR(hired) )
PARTITIONS 4;
Dalam hal ini hash akan dibuat berdasarkan hasil yang dihasilkan oleh fungsi YEAR() pada kolom 'dipekerjakan'.
Partisi KEY serupa dengan pengecualian bahwa pengguna menentukan kolom mana yang harus di-hash dan sisanya terserah MySQL untuk ditangani.
Sementara partisi HASH dan KEY mendistribusikan data secara acak ke seluruh jumlah partisi, RANGE dan LIST membiarkan pengguna memutuskan apa yang harus dilakukan. RANGE biasanya digunakan dengan waktu atau tanggal:
CREATE TABLE quarterly_report_status (
report_id INT NOT NULL,
report_status VARCHAR(20) NOT NULL,
report_updated TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
)
PARTITION BY RANGE ( UNIX_TIMESTAMP(report_updated) ) (
PARTITION p0 VALUES LESS THAN ( UNIX_TIMESTAMP('2008-01-01 00:00:00') ),
PARTITION p1 VALUES LESS THAN ( UNIX_TIMESTAMP('2008-04-01 00:00:00') ),
PARTITION p2 VALUES LESS THAN ( UNIX_TIMESTAMP('2008-07-01 00:00:00') ),
PARTITION p3 VALUES LESS THAN ( UNIX_TIMESTAMP('2008-10-01 00:00:00') ),
PARTITION p4 VALUES LESS THAN ( UNIX_TIMESTAMP('2009-01-01 00:00:00') ),
PARTITION p5 VALUES LESS THAN ( UNIX_TIMESTAMP('2009-04-01 00:00:00') ),
PARTITION p6 VALUES LESS THAN ( UNIX_TIMESTAMP('2009-07-01 00:00:00') ),
PARTITION p7 VALUES LESS THAN ( UNIX_TIMESTAMP('2009-10-01 00:00:00') ),
PARTITION p8 VALUES LESS THAN ( UNIX_TIMESTAMP('2010-01-01 00:00:00') ),
PARTITION p9 VALUES LESS THAN (MAXVALUE)
);
Itu juga dapat digunakan dengan jenis kolom lain:
CREATE TABLE employees (
id INT NOT NULL,
fname VARCHAR(30),
lname VARCHAR(30),
hired DATE NOT NULL DEFAULT '1970-01-01',
separated DATE NOT NULL DEFAULT '9999-12-31',
job_code INT NOT NULL,
store_id INT NOT NULL
)
PARTITION BY RANGE (store_id) (
PARTITION p0 VALUES LESS THAN (6),
PARTITION p1 VALUES LESS THAN (11),
PARTITION p2 VALUES LESS THAN (16),
PARTITION p3 VALUES LESS THAN MAXVALUE
);
Partisi LIST bekerja berdasarkan daftar nilai yang mengurutkan baris di beberapa partisi:
CREATE TABLE employees (
id INT NOT NULL,
fname VARCHAR(30),
lname VARCHAR(30),
hired DATE NOT NULL DEFAULT '1970-01-01',
separated DATE NOT NULL DEFAULT '9999-12-31',
job_code INT,
store_id INT
)
PARTITION BY LIST(store_id) (
PARTITION pNorth VALUES IN (3,5,6,9,17),
PARTITION pEast VALUES IN (1,2,10,11,19,20),
PARTITION pWest VALUES IN (4,12,13,14,18),
PARTITION pCentral VALUES IN (7,8,15,16)
);
Apa gunanya menggunakan partisi yang mungkin Anda tanyakan? Poin utamanya adalah bahwa pencarian secara signifikan lebih cepat dibandingkan dengan tabel yang tidak dipartisi. Katakanlah Anda ingin mencari baris yang dibuat pada bulan tertentu. Jika Anda memiliki data yang disimpan dalam tabel selama beberapa tahun, ini akan menjadi tantangan - indeks harus digunakan dan, seperti yang kita ketahui, indeks membantu menemukan baris tetapi mengakses baris tersebut akan menghasilkan banyak pembacaan acak dari seluruh meja. Jika Anda memiliki partisi yang dibuat berdasarkan tahun-bulan, MySQL hanya dapat membaca semua baris dari partisi tertentu - tidak perlu mengakses indeks, tidak perlu melakukan pembacaan acak:cukup baca semua data dari partisi, secara berurutan, dan kami siap.
Partisi juga sangat berguna dalam menangani rotasi data. Jika MySQL dapat dengan mudah mengidentifikasi baris untuk dihapus dan memetakannya ke satu partisi, alih-alih menjalankan DELETE FROM tabel WHERE ..., yang akan menggunakan indeks untuk menemukan baris, Anda dapat memotong partisi. Ini sangat berguna dengan pemartisian RANGE - mengikuti contoh di atas, jika kita ingin menyimpan data hanya selama 2 tahun, kita dapat dengan mudah membuat tugas cron, yang akan menghapus partisi lama dan membuat partisi baru yang kosong untuk bulan depan.
Kompresi InnoDB
Jika kita memiliki volume data yang besar (belum tentu memikirkan database), hal pertama yang terlintas di benak kita adalah mengompresnya. Ada banyak alat yang menyediakan opsi untuk mengompres file Anda, yang secara signifikan mengurangi ukurannya. InnoDB juga memiliki opsi untuk itu - MySQL dan MariaDB mendukung kompresi InnoDB. Keuntungan utama menggunakan kompresi adalah pengurangan aktivitas I/O. Data, ketika dikompresi, lebih kecil sehingga lebih cepat untuk membaca dan menulis. Halaman InnoDB tipikal berukuran 16KB, untuk SSD ini adalah 4 operasi I/O untuk membaca atau menulis (SSD biasanya menggunakan halaman 4KB). Jika kami berhasil mengompres 16KB menjadi 4KB, kami hanya mengurangi operasi I/O sebanyak empat. Itu tidak terlalu membantu banyak mengenai dataset ke rasio memori. Sebenarnya, itu bahkan dapat memperburuknya - MySQL, untuk beroperasi pada data, harus mendekompresi halaman. Namun ia membaca halaman terkompresi dari disk. Ini menghasilkan kumpulan buffer InnoDB yang menyimpan 4KB data terkompresi dan 16KB data tidak terkompresi. Tentu saja, ada algoritme untuk menghapus data yang tidak dibutuhkan (halaman yang tidak dikompresi akan dihapus jika memungkinkan, hanya menyimpan satu yang terkompresi di memori) tetapi Anda tidak dapat mengharapkan terlalu banyak peningkatan di area ini.
Penting juga untuk diingat bagaimana kompresi bekerja terkait penyimpanan. Solid state drive adalah norma untuk server database hari ini dan mereka memiliki beberapa karakteristik khusus. Mereka cepat, mereka tidak terlalu peduli apakah lalu lintas berurutan atau acak (meskipun mereka masih lebih suka akses berurutan daripada acak). Mereka mahal untuk volume besar. Mereka menderita "usang" karena mereka dapat menangani jumlah siklus penulisan yang terbatas. Kompresi sangat membantu di sini - dengan mengurangi ukuran data pada disk, kami mengurangi biaya lapisan penyimpanan untuk database. Dengan mengurangi ukuran data yang kami tulis ke disk, kami meningkatkan masa pakai SSD.
Sayangnya, meskipun kompresi membantu, untuk volume data yang lebih besar mungkin masih belum cukup. Langkah lain adalah mencari sesuatu selain InnoDB.
MyRocks
MyRocks adalah mesin penyimpanan yang tersedia untuk MySQL dan MariaDB yang didasarkan pada konsep yang berbeda dari InnoDB. Rekan saya, Sebastian Insausti, memiliki blog yang bagus tentang penggunaan MyRocks dengan MariaDB. Intinya adalah, karena desainnya (menggunakan Log Structured Merge, LSM), MyRocks secara signifikan lebih baik dalam hal kompresi daripada InnoDB (yang didasarkan pada struktur B+Tree). MyRocks dirancang untuk menangani data dalam jumlah besar dan mengurangi jumlah penulisan. Itu berasal dari Facebook, di mana volume data besar dan persyaratan untuk mengakses data tinggi. Jadi penyimpanan SSD - tetap saja, dalam skala besar, setiap keuntungan dalam kompresi sangat besar. MyRocks bahkan dapat memberikan kompresi hingga 2x lebih baik daripada InnoDB (yang berarti Anda memangkas jumlah server menjadi dua). Ini juga dirancang untuk mengurangi amplifikasi penulisan (jumlah penulisan yang diperlukan untuk menangani perubahan konten baris) - ini membutuhkan penulisan 10x lebih sedikit daripada InnoDB. Ini, jelas, mengurangi beban I/O tetapi, yang lebih penting, ini akan meningkatkan masa pakai SSD sepuluh kali lipat dibandingkan dengan menyerahkan beban yang sama menggunakan InnoDB). Dari sudut pandang kinerja, semakin kecil volume data, semakin cepat aksesnya sehingga mesin penyimpanan seperti itu juga dapat membantu mengeluarkan data dari database dengan lebih cepat (walaupun itu bukan prioritas tertinggi saat mendesain MyRocks).
Penyimpanan Data Kolom
Sumber daya terkait Manajemen Kinerja ClusterControl Memahami Pengaruh Latensi Tinggi pada Ketersediaan Tinggi Solusi MySQL dan MariaDB Lembar Cheat Kinerja MySQLPada titik tertentu yang dapat kita lakukan adalah mengakui bahwa kita tidak dapat menangani volume data seperti itu menggunakan MySQL. Tentu, Anda dapat memecahkannya, Anda dapat melakukan hal-hal yang berbeda tetapi pada akhirnya itu tidak masuk akal lagi. Saatnya mencari solusi tambahan. Salah satunya adalah menggunakan penyimpanan data kolom - database, yang dirancang dengan mempertimbangkan analitik data besar. Tentu, mereka tidak akan membantu dengan jenis lalu lintas OLTP tetapi analitik cukup standar saat ini karena perusahaan mencoba untuk didorong oleh data dan membuat keputusan berdasarkan angka yang tepat, bukan data acak. Ada banyak penyimpanan data berbentuk kolom tetapi kami ingin menyebutkan di sini dua di antaranya. MariaDB AX dan ClickHouse. Kami memiliki beberapa blog yang menjelaskan apa itu MariaDB AX dan bagaimana MariaDB AX dapat digunakan. Yang penting, MariaDB AX dapat ditingkatkan dalam bentuk cluster, meningkatkan kinerja. ClickHouse adalah opsi lain untuk menjalankan analitik - ClickHouse dapat dengan mudah dikonfigurasi untuk mereplikasi data dari MySQL, seperti yang telah kita bahas di salah satu posting blog kami. Cepat, gratis, dan juga dapat digunakan untuk membentuk cluster dan memisahkan data untuk kinerja yang lebih baik lagi.
Kesimpulan
Kami berharap posting blog ini memberi Anda wawasan tentang seberapa besar volume data dapat ditangani di MySQL atau MariaDB. Untungnya, ada beberapa opsi yang dapat kita gunakan dan, pada akhirnya, jika kita tidak dapat benar-benar membuatnya bekerja, ada alternatif yang baik.