Apa alasan ** BUKAN ** untuk menggunakan mesin penyimpanan MEMORY di MySQL?

28

Baru-baru ini saya menemukan bahwa MySQL memiliki mesin "memori" yang saya tidak sadari (sebagian besar pekerjaan basis data saya adalah untuk proyek hobi jadi saya belajar apa yang saya butuhkan saat saya pergi). Sepertinya opsi ini harus memberi saya peningkatan kinerja yang drastis, jadi saya ingin tahu apakah ada kekurangan yang menyertainya. Dua yang saya tahu adalah:

  1. Saya perlu memiliki RAM yang cukup untuk menahan tabel tersebut.
  2. Tabel hilang jika mesin dimatikan.

Saya percaya # 1 seharusnya tidak menjadi masalah karena saya menggunakan AWS EC2 dan dapat pindah ke tipe instance dengan lebih banyak memori jika diperlukan. Saya percaya saya dapat mengurangi # 2 dengan membuang kembali ke disk sesuai kebutuhan.

Apa masalah lain yang ada? Dapatkah mesin memori memberikan kinerja yang lebih buruk daripada MyISAM atau InnoDB? Saya rasa saya membaca sesuatu yang indeksnya berbeda dengan mesin ini; Apakah ini sesuatu yang perlu saya khawatirkan?

Michael McGowan
sumber

Jawaban:

27

Melihat daftar ketersediaan fitur di http://dev.mysql.com/doc/refman/5.1/en/memory-storage-engine.html dua masalah yang mungkin muncul:

  1. Tidak ada transaksi atau dukungan FK, yang berarti Anda harus mengelola integritas transaksional dan integritas referensial dalam kode Anda sendiri yang diperlukan (yang bisa menjadi jauh lebih efisien daripada membiarkan DB melakukan ini untuk Anda, meskipun itu sangat tergantung pada aplikasi Anda. pola perilaku yang diharapkan).
  2. Hanya penguncian tingkat tabel: ini bisa menjadi penghalang yang signifikan untuk skalabilitas jika aplikasi Anda membutuhkan beberapa penulis bersamaan ke set tabel yang sama atau dalam kasus di mana operasi membaca Anda menggunakan kunci untuk memastikan data yang konsisten dibaca - dalam kasus seperti itu sebuah tabel berbasis disk yang mendukung granularity kunci jauh lebih baik akan melakukan jauh lebih baik jika cukup kontennya saat ini di-cache dalam RAM.

Selain itu, dengan asumsi Anda memiliki RAM yang cukup, tabel berbasis memori harus lebih cepat dari yang berbasis disk. Jelas Anda perlu mempertimbangkan untuk mengambil snapshot ke disk untuk mengatasi masalah apa yang terjadi ketika instance server diatur ulang, yang kemungkinan besar akan sepenuhnya meniadakan manfaat kinerja secara keseluruhan jika data perlu sering ditangkap (jika Anda dapat hidup dengan kehilangan satu hari dari data dalam keadaan seperti itu Anda hanya bisa mengambil cadangan sekali sehari, tetapi dalam kebanyakan kasus itu tidak dapat diterima).

Alternatif lain adalah:

  1. Gunakan tabel berbasis disk, tetapi pastikan Anda memiliki lebih dari cukup RAM untuk menampung semuanya dalam RAM pada waktu tertentu (dan "cukup RAM" mungkin lebih dari yang Anda pikirkan karena Anda harus memperhitungkan proses lain pada mesin, OS IO buffer / cache dan sebagainya)
  2. Memindai seluruh konten (semua data dan halaman indeks) dari tabel pada setiap startup untuk memuat ulang konten ke dalam memori dengan SELECT * FROM <table> ORDER BY <pkey fields>untuk setiap tabel diikuti oleh SELECT <indexed fields> FROM <table> ORDER BY <index fields>untuk setiap indeks

Dengan cara ini semua data Anda dalam RAM, Anda hanya perlu khawatir tentang kinerja I / O untuk operasi penulisan. Jika rangkaian kerja aplikasi Anda jauh lebih kecil daripada seluruh DB (yang biasanya terjadi - di sebagian besar aplikasi sebagian besar pengguna hanya akan melihat data terbaru paling banyak jika waktu itu), Anda mungkin lebih baik menjadi lebih selektif tentang berapa banyak Anda memindai untuk memuat ke dalam memori, memungkinkan sisanya untuk dimuat dari disk sesuai permintaan.

David Spillett
sumber
Mengapa Anda membutuhkan integritas transaksional untuk basis data dalam memori? Jika listrik padam, Anda kehilangan segalanya.
Osa
@ Esa: dengan asumsi itu memungkinkan akses bersamaan daripada membuat serialisasi segalanya, Anda akan menginginkan beberapa bentuk manajemen integritas untuk itu.
David Spillett
14

Ada banyak kasus untuk tidak menggunakan mesin penyimpanan memori - dan ketika InnoDB akan lebih cepat. Anda hanya perlu memikirkan konkurensi dan bukan tes ulir tunggal yang sepele.

Jika Anda memiliki kumpulan buffer yang cukup besar, maka InnoDB akan menjadi memori sepenuhnya untuk operasi baca juga. Database memiliki cache . Mereka menghangatkan diri!

Juga - jangan meremehkan nilai penguncian tingkat baris dan MVCC (pembaca tidak memblokir penulis). Mungkin "lebih lambat" ketika menulis harus bertahan ke disk. Tapi setidaknya Anda tidak akan memblokir selama operasi penulisan seperti Anda berada di meja memori (tidak ada MVCC; penguncian tingkat tabel).

Morgan Tocker
sumber
3

Untuk catatan. Saya menguji tabel Mysql di Memori untuk menyimpan beberapa informasi. Dan saya menguji PHP APC (APCu) untuk menyimpan informasi yang sama.

Untuk 58000 pendaftar. (varchar + integer + date).

  1. Informasi asli 24mb dalam format teks (format csv).
  2. APC PHP menggunakan 44,7mb RAM.
  3. Tabel Mysql menggunakan 575mb RAM.

Tabel hanya memiliki satu indeks jadi saya tidak berpikir itu adalah faktor utama.

Kesimpulan:

Tabel memori bukan pilihan untuk tabel "besar" karena menggunakan terlalu banyak memori.

magallanes
sumber
2
Ini adalah jawaban yang terlalu disederhanakan. Mesin penyimpanan MEMORY dapat disetel dengan menggunakan tipe data yang lebih kecil, mendefinisikan BTREE secara eksplisit sebagai tipe indeks, dan membatasi jumlah data yang dimuat ke dalam RAM. Ini masih merupakan opsi yang layak untuk set yang lebih kecil. Ada juga faktor-faktor lain seperti I / O disk yang agresif. Lihat posting saya dba.stackexchange.com/questions/6156/… dan dba.stackexchange.com/questions/2868/… )
RolandoMySQLDBA
Bahkan, saya memeriksa mengubah indeks (dan bahkan menghapusnya sepenuhnya) dan ukurannya tidak banyak berubah (termasuk rekonstruksi tabel dari awal). IMHO Mysql sedang melakukan sesuatu di bawah tenda, mungkin semacam optimasi atau mengalokasikan ukuran terbesar per kolom (seperti di varchar).
magallanes
6
Alasannya hampir pasti karena VARCHAR Anda: "MEMORY tables use a fixed-length row-storage format. Variable-length types such as VARCHAR are stored using a fixed length." dev.mysql.com/doc/refman/5.6/en/memory-storage-engine.html Secara efektif akan muncul VARCHAR menjadi CHAR dengan mesin MEMORY.
Matius1471
2

Kerugian lain dari tabel berbasis MEMORY adalah bahwa mereka tidak dapat dirujuk beberapa kali dalam permintaan yang sama. Setidaknya perilaku itu ditemukan sampai v5.4. Bagaimana dengan CTE (sejak v8.x) tidak perlu menggunakan tabel perantara berbasis mem untuk prosedur kompleks.

Kondybas
sumber
1

Menurut manual MySQL dan MariaDB, BLOB dan CLOB (berbagai jenis TEXT) tidak didukung oleh penyimpanan MEMORY. Untuk keperluan kita sendiri, ini membuat mesin penyimpanan MEMORY hampir tidak berguna.

http://dev.mysql.com/doc/refman/5.7/en/memory-storage-engine.html

Tabel MEMORY tidak dapat berisi kolom BLOB atau TEXT.

https://mariadb.com/kb/en/mariadb/memory-storage-engine/

Tipe panjang variabel seperti VARCHAR dapat digunakan dalam tabel MEMORY. Kolom BLOB atau TEXT tidak didukung untuk tabel MEMORY.

Ketika mencoba mengubah hanya sebagian dari database menjadi penyimpanan MEMORY, saya menemukan bahwa kunci asing mesin antar-penyimpanan tidak didukung. Jadi, semua tabel, yang harus memiliki referensi kunci asing ke tabel, berisi BLOB / CLOB juga harus dalam jenis penyimpanan non-memori (setidaknya, ini mempengaruhi tabel anak InnoDB).

pengguna2134886
sumber
1

Tabel MEMORY tidak dimaksudkan untuk penyimpanan persisten, khususnya subset besar data atau apa pun di mana penyimpanan sangat penting. Tujuan terbaik mereka dari pengalaman saya adalah untuk menyimpan catatan sementara selama pembuatan dan populasi tabel sementara selama prosedur kompleks, yang berkinerja lebih cepat secara signifikan daripada kebanyakan tipe tabel lainnya untuk tujuan ini asalkan ambang batas buffer utama Anda untuk mesin diatur cukup tinggi untuk tidak menimbulkan tulis disk. Ini dapat mengoperasikan urutan besarnya lebih cepat dari MyISAM atau InnoDB untuk tujuan ini karena tidak ada disk I / O, dan dalam kasus tabel yang dienkapsulasi dalam prosedur tertentu, pengindeksan dan hubungan tidak memiliki signifikansi sebanyak mereka akan di mana kegigihan diharapkan.

mopsyd
sumber
1

Selain jawaban sebelumnya. langsung dari manual MySQL 5.7:

"Kinerja MEMORY dibatasi oleh pertikaian yang dihasilkan dari eksekusi single-thread dan overhead kunci tabel saat memproses pembaruan. Ini membatasi skalabilitas ketika beban meningkat, terutama untuk campuran pernyataan yang mencakup penulisan."

... dan ini adalah batasan yang sangat nyata. Misalnya: ketika Anda memiliki beberapa sesi mencoba membuat tabel temp MEMORY cepat bagus, threading tunggal dapat menyebabkan hambatan kinerja yang serius.

Eljuan
sumber