MyISAM versus InnoDB [ditutup]

857

Saya sedang mengerjakan proyek yang melibatkan banyak basis data menulis, saya katakan ( 70% sisipan dan 30% berbunyi ). Rasio ini juga akan mencakup pembaruan yang saya anggap satu baca dan satu tulis. Bacaannya bisa kotor (misalnya saya tidak perlu informasi akurat 100% pada saat dibaca).
Tugas tersebut akan melakukan lebih dari 1 juta transaksi basis data per jam.

Saya sudah membaca banyak hal di web tentang perbedaan antara MyISAM dan InnoDB, dan MyISAM sepertinya pilihan yang jelas bagi saya untuk database / tabel tertentu yang akan saya gunakan untuk tugas ini. Dari apa yang saya baca, InnoDB bagus jika transaksi diperlukan karena penguncian tingkat baris didukung.

Adakah yang punya pengalaman dengan jenis beban ini (atau lebih tinggi)? Apakah MyISAM cara untuk pergi?

pengguna2013
sumber
13
The MySQL Kinerja Blog adalah sumber daya yang besar untuk hal semacam ini.
ceejayoz
3
Ini akan sedikit tergantung pada apakah sistem Anda OLTP atau lebih berorientasi datawarehouse (di mana sebagian besar penulisan adalah pemuatan massal).
nos
35
MyISAM tidak mendukung penguncian baris, transaksi, bahkan tidak mendukung kunci asing ... sial, karena tidak dapat memberikan ACID , bahkan hampir tidak dapat dianggap sebagai basis data yang tepat! Inilah sebabnya mengapa InnoDB telah menjadi mesin default sejak MySQL 5.5 ... tetapi, untuk alasan apa pun, MyISAM terus menjadi mesin default untuk tabel yang dibuat dalam PhpMyAdmin, jadi banyak basis data amatir sejak dijalankan pada MyISAM.
BlueRaja - Danny Pflughoeft
Lihat semua mesin MySql DB yang dibandingkan
Somnath Muluk

Jawaban:

523

Saya telah membahas secara singkat pertanyaan ini dalam sebuah tabel sehingga Anda dapat menyimpulkan apakah akan menggunakan InnoDB atau MyISAM .

Berikut ini adalah ikhtisar kecil dari mesin penyimpanan db yang harus Anda gunakan dalam situasi apa:

                                                 MyISAM InnoDB
-------------------------------------------------- --------------
Diperlukan pencarian teks lengkap Ya 5.6.4
-------------------------------------------------- --------------
Membutuhkan transaksi Ya
-------------------------------------------------- --------------
Pertanyaan pilih yang sering. Ya      
-------------------------------------------------- --------------
Sisipkan, perbarui, hapus Ya yang sering
-------------------------------------------------- --------------
Penguncian baris (multi pemrosesan pada satu tabel) Ya
-------------------------------------------------- --------------
Desain basis relasional Ya

Ringkasan

  • Di hampir semua keadaan, InnoDB adalah cara terbaik untuk pergi
  • Tapi, sering membaca, hampir tidak ada tulisan, gunakan MyISAM
  • Pencarian teks lengkap di MySQL <= 5.5, gunakan MyISAM
developer99
sumber
11
InnoDB memiliki indeks teks lengkap di MySQL 5.6, tetapi sejauh ini, mereka tidak benar-benar siap untuk digunakan produksi.
Bill Karwin
3
Sesuai dengan 12.9. Fungsi Pencarian Teks Lengkap , “Indeks teks lengkap hanya dapat digunakan dengan tabel InnoDB atau MyISAM”. Tampaknya OK untuk MySQL> = 5.6, namun halaman yang sama untuk MySQL 5.5, masih mengatakan "indeks teks lengkap hanya dapat digunakan dengan tabel MyISAM". Tabel di atas dapat diperbarui untuk mengatakan bagaimana perbedaannya dengan versi MySQL. Sayangnya, sejauh ini, MySQL 5.5 tampaknya menjadi standar.
Hibou57
2
Apa yang dimaksud dengan: InnoDB - full-text: 5.6.4?? Apakah ya atau tidak?
2
MyISAM juga menyimpan jumlah baris secara internal. Oleh karena itu, fungsi Count () hampir gratis di MyISAM, sementara itu membutuhkan waktu yang cukup lama di InnoDB.
Hedeshy
3
tabel yang bagus, tetapi menambahkan baris untuk kualitas dan stabilitas, MyIsam = tidak, innoDB = ya akan membuatnya lebih baik
pilavdzice
268

Saya bukan pakar basis data, dan saya tidak berbicara dari pengalaman. Namun:

Tabel MyISAM menggunakan penguncian tingkat-tabel . Berdasarkan taksiran kunjungan Anda, Anda memiliki hampir 200 penulisan per detik. Dengan MyISAM, hanya satu di antaranya yang dapat berlangsung kapan saja . Anda harus memastikan bahwa perangkat keras Anda dapat mengikuti transaksi ini untuk menghindari overrun, yaitu, permintaan tunggal dapat mengambil tidak lebih dari 5 ms.

Itu menunjukkan kepada saya Anda akan membutuhkan mesin penyimpanan yang mendukung penguncian tingkat baris, yaitu, InnoDB.

Di sisi lain, itu seharusnya cukup sepele untuk menulis beberapa skrip sederhana untuk mensimulasikan beban dengan masing-masing mesin penyimpanan, kemudian membandingkan hasilnya.

rix0rrr
sumber
12
Hampir 200? Jika transaksi rata-rata membuat 2,5 kueri, itu [(2,5 * 1M) / 3600s =] lebih dekat ke 700.
Ozzy
12
Saya juga tidak setuju a single query can take no more than 5mskarena Anda membuat 2 asumsi yang tidak mungkin; A: semua pertanyaan membutuhkan tabel yang sama & B: hanya ada 1 koneksi yang tersedia! Saya harus memberi tahu Anda bahwa pengaturan Linux & MySQL 5.5 dengan RAM tinggi dapat mendukung sebanyak 10.000 koneksi simultan (Lihat: dev.mysql.com/doc/refman//5.5/id/too-many-connections.html )
Ozzy
152
Saat sebuah tabel dikunci, hanya satu kueri yang dapat menjalankannya pada satu waktu. Tidak masalah jika server mendukung 10.000 koneksi secara bersamaan, masing-masing akan membuat cadangan saat tabel terkunci.
Ryaner
2
Mungkin juga bermanfaat untuk mengetahui bahwa MyISAM mendukung indeks spasial sementara InnoDB tidak. Dan MyISAM tampaknya tidak menggunakan kunci asing meskipun itu tidak mencegah pembuatan kunci.
kriver
4
@kriver: Anda tidak dapat memiliki kunci asing di tabel MyISAM. Anda dapat memasukkan definisi FK dalam pernyataan CREATE TABLE tetapi mereka (definisi) diabaikan begitu saja.
ypercubeᵀᴹ
191

Orang-orang sering berbicara tentang kinerja, membaca vs menulis, kunci asing, dll. Tetapi ada satu fitur lain yang harus dimiliki untuk mesin penyimpanan menurut saya: pembaruan atom.

Coba ini:

  1. Terbitkan PEMBARUAN terhadap tabel MyISAM Anda yang membutuhkan waktu 5 detik.
  2. Saat UPDATE sedang berlangsung, katakan 2,5 detik, tekan Ctrl-C untuk menghentikannya.
  3. Amati efeknya di atas meja. Berapa banyak baris yang diperbarui? Berapa banyak yang tidak diperbarui? Apakah tabelnya bahkan dapat dibaca, atau apakah rusak ketika Anda menekan Ctrl-C?
  4. Coba percobaan yang sama dengan UPDATE terhadap tabel InnoDB, mengganggu permintaan yang sedang berlangsung.
  5. Amati tabel InnoDB. Baris nol diperbarui. InnoDB telah memastikan Anda memiliki pembaruan atom, dan jika pembaruan penuh tidak dapat dilakukan, itu memutar kembali seluruh perubahan. Juga, tabelnya tidak rusak. Ini berfungsi bahkan jika Anda gunakan killall -9 mysqlduntuk mensimulasikan kecelakaan.

Kinerja memang diinginkan, tetapi tidak kehilangan data seharusnya mengalahkan itu.

Bill Karwin
sumber
4
Sebagai catatan, karakteristik lain dari basis data ACID - Konsistensi, Isolasi, dan Daya Tahan - juga tidak didukung oleh MyISAM.
Bill Karwin
Control-C tidak boleh merusak tabel - karena dalam PERIKSA TABEL akan mengembalikan kesuksesan dan semua pertanyaan akan dilanjutkan tanpa kesalahan. MyISAM akan membatalkan pembaruan tanpa memperbarui semua catatan, tetapi tabel akan mempertahankan integritas struktural internal. Membunuh mysqld dengan SIGTERM akan memiliki efek yang sama. Namun jika Anda memberikannya SIGKILL (kill -9) atau sinyal menabrak (atau menghasilkannya sendiri saat menabrak bug), atau jika OS rusak / daya hilang, maka itu adalah cerita yang berbeda - Anda dapat melihat Korupsi tingkat MyISAM.
Sasha Pachev
1
InnoDB dapat merusak dirinya sendiri secara meriah, biasanya lebih meriah daripada MyISAM saat itu. Ironi ACID adalah bahwa kita memiliki gagasan tentang semua atau tidak sama sekali. Jadi ketika InnoDB tidak dapat memberikan semuanya, ia tidak memberikan apa pun - penegasan internal, dan ia menolak untuk berjalan sama sekali karena satu byte dalam beberapa struktur salah - 90% dari waktu itu bisa diabaikan dan paling banyak hanya mempengaruhi satu tabel. Server Percona terbaru memiliki opsi untuk menghadapinya - innodb_pass_corrupt_table.
Sasha Pachev
1
Saya mencari info seperti ini dari 3 hari terakhir, sekarang saya dapat ini. InnoDB adalah yang terbaik. Terima kasihBill Karwin
user3833682
3
@ flow2k, Hampir tidak ada, hari ini. Pada pekerjaan terakhir saya, kami menggunakan MyISAM untuk satu tabel di satu server, dan satu-satunya alasan adalah MyISAM mampu menyimpan tabel spesifik itu dalam ruang yang lebih sedikit daripada yang dimiliki InnoDB. Kami dibatasi pada ruang disk, jadi kami harus menggunakan MyISAM hingga kami dapat memindahkan database ke server lain. Di pekerjaan baru saya, sudah ada kebijakan bahwa setiap tabel harus InnoDB.
Bill Karwin
138

Saya telah bekerja pada sistem volume tinggi menggunakan MySQL dan saya sudah mencoba MyISAM dan InnoDB.

Saya menemukan bahwa penguncian tingkat meja di MyISAM menyebabkan masalah kinerja serius untuk beban kerja kami yang terdengar mirip dengan Anda. Sayangnya saya juga menemukan bahwa kinerja di bawah InnoDB juga lebih buruk dari yang saya harapkan.

Pada akhirnya saya menyelesaikan masalah pertengkaran dengan memecah-mecah data sedemikian rupa sehingga sisipan masuk ke tabel "panas" dan memilih tidak pernah menanyakan tabel panas.

Ini juga memungkinkan penghapusan (data sensitif terhadap waktu dan kami hanya mempertahankan nilai X hari) terjadi pada tabel "basi" yang sekali lagi tidak tersentuh oleh kueri pemilihan. InnoDB tampaknya memiliki kinerja yang buruk pada penghapusan massal, jadi jika Anda berencana membersihkan data, Anda mungkin ingin menyusunnya sedemikian rupa sehingga data lama ada di tabel basi yang dapat dengan mudah dijatuhkan daripada menjalankan penghapusan di atasnya.

Tentu saja saya tidak tahu apa aplikasi Anda, tetapi mudah-mudahan ini memberi Anda wawasan tentang beberapa masalah dengan MyISAM dan InnoDB.

alanc10n
sumber
3
'Pada akhirnya saya menyelesaikan masalah pertengkaran dengan memecah-mecah data sedemikian rupa sehingga memasukkan ke dalam tabel "panas" dan memilih tidak pernah menanyakan tabel panas. " - bukankah pada dasarnya apa gunanya kolam penyangga ?
BlueRaja - Danny Pflughoeft
15
Danny - Tidak, tidak juga. Menyetel pengaturan server itu penting, tetapi sama sekali bukan pengganti untuk penataan skema Anda yang bijaksana. Jika Anda memiliki DB jauh, jauh lebih besar dari RAM yang tersedia dan pola akses yang menyentuh data secara acak di seluruh DB, maka semua penyangga kumpulan penyangga di dunia tidak akan membantu Anda. Jika Anda memahami data dan pola aksesnya maka Anda dapat mengurangi banyak rasa sakit melalui desain yang cermat.
alanc10n
66

Agak terlambat ke permainan ... tapi di sini ada posting yang cukup komprehensif yang saya tulis beberapa bulan lalu , merinci perbedaan utama antara MYISAM dan InnoDB. Raih secangkir teh (dan mungkin biskuit), dan nikmati.


Perbedaan utama antara MyISAM dan InnoDB adalah dalam integritas referensial dan transaksi. Ada juga perbedaan lain seperti penguncian, kembalikan, dan pencarian teks lengkap.

Integritas referensial

Integritas referensial memastikan bahwa hubungan antar tabel tetap konsisten. Lebih khusus lagi, ini berarti ketika sebuah tabel (mis. Listing) memiliki kunci asing (mis. ID Produk) yang menunjuk ke tabel yang berbeda (mis. Produk), ketika pembaruan atau penghapusan terjadi pada tabel menunjuk-ke, perubahan-perubahan ini mengalir ke penautan meja. Dalam contoh kami, jika suatu produk diganti namanya, kunci asing tabel penautan juga akan diperbarui; jika suatu produk dihapus dari tabel 'Produk', setiap daftar yang mengarah ke entri yang dihapus juga akan dihapus. Selain itu, setiap listing baru harus memiliki kunci asing yang menunjuk ke entri yang ada dan valid.

InnoDB adalah DBMS relasional (RDBMS) dan dengan demikian memiliki integritas referensial, sedangkan MyISAM tidak.

Transaksi & Atomicity

Data dalam tabel dikelola menggunakan pernyataan Bahasa Manipulasi Data (DML), seperti SELECT, INSERT, UPDATE, dan DELETE. Grup transaksi yang menggabungkan dua atau lebih pernyataan DML menjadi satu unit kerja, sehingga seluruh unit diterapkan, atau tidak ada satu pun di antaranya.

MyISAM tidak mendukung transaksi sedangkan InnoDB tidak.

Jika operasi terganggu saat menggunakan tabel MyISAM, operasi dibatalkan segera, dan baris (atau bahkan data dalam setiap baris) yang terpengaruh tetap terpengaruh, bahkan jika operasi tidak selesai.

Jika operasi terganggu saat menggunakan tabel InnoDB, karena menggunakan transaksi, yang memiliki atomicity, setiap transaksi yang tidak selesai tidak akan berpengaruh, karena tidak ada komit dibuat.

Mengunci meja vs Mengunci baris

Ketika kueri berjalan terhadap tabel MyISAM, seluruh tabel di mana kueri akan dikunci. Ini berarti pertanyaan selanjutnya hanya akan dieksekusi setelah yang sekarang selesai. Jika Anda membaca tabel besar, dan / atau ada operasi baca dan tulis yang sering, ini bisa berarti tumpukan pertanyaan yang sangat besar.

Ketika kueri berjalan terhadap tabel InnoDB, hanya baris yang terlibat yang dikunci, sisa tabel tetap tersedia untuk operasi CRUD. Ini berarti kueri dapat berjalan secara bersamaan di tabel yang sama, asalkan mereka tidak menggunakan baris yang sama.

Fitur ini di InnoDB dikenal sebagai konkurensi. Sehebat konkurensi, ada kelemahan utama yang berlaku pada rentang tabel tertentu, di mana ada overhead dalam peralihan di antara thread kernel, dan Anda harus menetapkan batas pada thread kernel untuk mencegah server berhenti. .

Transaksi & Kembalikan

Saat Anda menjalankan operasi di MyISAM, perubahannya diatur; di InnoDB, perubahan itu dapat dibatalkan. Perintah yang paling umum digunakan untuk mengendalikan transaksi adalah COMMIT, ROLLBACK dan SAVEPOINT. 1. COMMIT - Anda dapat menulis beberapa operasi DML, tetapi perubahan hanya akan disimpan ketika KOMIT dibuat 2. ROLLBACK - Anda dapat membuang semua operasi yang belum dilakukan. 3. SAVEPOINT - menetapkan poin dalam daftar operasi yang dapat dikembalikan ke operasi ROLLBACK

Keandalan

MyISAM tidak menawarkan integritas data - Kegagalan perangkat keras, shutdown yang tidak bersih dan operasi yang dibatalkan dapat menyebabkan data menjadi rusak. Ini akan membutuhkan perbaikan penuh atau membangun kembali indeks dan tabel.

InnoDB, di sisi lain, menggunakan log transaksional, buffer penulisan ganda dan pemeriksaan otomatis dan validasi untuk mencegah korupsi. Sebelum InnoDB membuat perubahan, itu merekam data sebelum transaksi menjadi file tablespace sistem yang disebut ibdata1. Jika ada kerusakan, InnoDB akan melakukan autorecover melalui pemutaran ulang log tersebut.

Pengindeksan FULLTEXT

InnoDB tidak mendukung pengindeksan FULLTEXT hingga MySQL versi 5.6.4. Pada penulisan posting ini, banyak versi MySQL penyedia hosting bersama masih di bawah 5.6.4, yang berarti pengindeksan FULLTEXT tidak didukung untuk tabel InnoDB.

Namun, ini bukan alasan yang sah untuk menggunakan MyISAM. Yang terbaik adalah beralih ke penyedia hosting yang mendukung versi MySQL terbaru. Bukan berarti tabel MyISAM yang menggunakan pengindeksan FULLTEXT tidak dapat dikonversi ke tabel InnoDB.

Kesimpulan

Kesimpulannya, InnoDB harus menjadi mesin penyimpanan pilihan Anda. Pilih MyISAM atau tipe data lain ketika mereka melayani kebutuhan tertentu.

d4nyll
sumber
Saya membuat skrip checksum sesi php dan sebagian besar kunci saya adalah string acak [az09] ... Innodb mengambil lebih dari 30ms untuk melakukan INSERT ON DUPLICATE KEY UPDATEjadi saya mencoba MyISAM dan sekarang turun ke <1 ms ... Banyak jawaban yang saya lihat mengatakan bahwa innodb mengalami kesulitan untuk berurusan dengan kunci unik 'acak' (string acak) ... Apakah Anda punya masukan untuk kami tentang itu? Sebenarnya saya bertanya-tanya tentang dampaknya harus menggunakan MyISAM tetapi jawaban Anda yang luar biasa membuat saya sadar bahwa itu adalah cara untuk menangani kasus tertentu.
Louis Loudog Trottier
64

Untuk memuat dengan lebih banyak menulis dan membaca, Anda akan mendapat manfaat dari InnoDB. Karena InnoDB menyediakan penguncian baris daripada penguncian meja, SELECTs Anda bisa bersamaan, tidak hanya dengan satu sama lain tetapi juga dengan banyak INSERTs. Namun, kecuali Anda bermaksud menggunakan transaksi SQL, setel InnoDB commit flush menjadi 2 ( innodb_flush_log_at_trx_commit ). Ini memberi Anda kembali banyak kinerja mentah yang Anda akan kehilangan ketika memindahkan tabel dari MyISAM ke InnoDB.

Juga pertimbangkan untuk menambahkan replikasi. Ini memberi Anda beberapa skala baca dan karena Anda menyatakan bahwa bacaan Anda tidak harus mutakhir, Anda dapat membiarkan replikasi sedikit ketinggalan. Pastikan bahwa itu dapat mengejar apa pun kecuali lalu lintas terberat atau akan selalu ada di belakang dan tidak akan pernah mengejar ketinggalan. Namun, jika Anda menggunakan cara ini, saya sangat menyarankan Anda mengisolasi pembacaan dari slave dan manajemen lag replikasi ke penangan database Anda. Jauh lebih sederhana jika kode aplikasi tidak mengetahui hal ini.

Akhirnya, perhatikan beban tabel yang berbeda. Anda tidak akan memiliki rasio baca / tulis yang sama di semua tabel. Beberapa meja yang lebih kecil dengan hampir 100% terbaca mampu untuk tetap MyISAM. Demikian juga, jika Anda memiliki beberapa tabel yang mendekati 100% tulis, Anda dapat mengambil manfaat dari INSERT DELAYED, tetapi itu hanya didukung di MyISAM ( DELAYEDklausa diabaikan untuk tabel InnoDB).

Tapi patokan pasti.

ahli statika
sumber
4
Apakah "InnoDB commit flush" yang Anda maksud innodb_flush_log_at_trx_commit?
ceejayoz
2
Saya menemukan posting Anda sangat berguna - terima kasih. Saat ini mengevaluasi kapan harus menggunakan MyISAM / InnoDB untuk tabel saya dan posting Anda sangat membantu. Bersulang.
starmonkey
2
dev.mysql.com/doc/refman/5.5/en/insert-delayed.html menyatakan: Untuk tabel MyISAM, jika tidak ada blok gratis di tengah file data, pernyataan SELECT dan INSERT bersamaan didukung. Dalam keadaan ini, Anda sangat jarang perlu menggunakan INSERT DITUNDA dengan MyISAM.
tymtam
Posting yang sangat informatif. Saya memiliki pertanyaan yang sama dengan op dan saya harus mengatakan bahwa posting Anda telah membuat saya tenang tentang keputusan mesin database saya. Terima kasih! ++
Joe Majewski
Catatan cepat: tertunda tidak lagi didukung di 5.7. Anda mungkin ingin menguji dengan LOW_PRIORITY sebagai gantinya.
webmat
59

Untuk menambah berbagai pilihan tanggapan di sini yang mencakup perbedaan mekanis antara kedua mesin, saya menyajikan studi perbandingan kecepatan empiris.

Dalam hal kecepatan murni, itu tidak selalu terjadi bahwa MyISAM lebih cepat dari InnoDB tetapi dalam pengalaman saya cenderung lebih cepat untuk lingkungan kerja MURNI MURNI dengan faktor sekitar 2,0-2,5 kali. Jelas ini tidak sesuai untuk semua lingkungan - seperti yang ditulis orang lain, MyISAM tidak memiliki hal-hal seperti transaksi dan kunci asing.

Saya telah melakukan sedikit pembandingan di bawah ini - Saya telah menggunakan python untuk perulangan dan perpustakaan timeit untuk perbandingan waktu. Untuk menarik saya juga menyertakan mesin memori, ini memberikan kinerja terbaik di seluruh papan meskipun hanya cocok untuk tabel yang lebih kecil (Anda terus menerus menemukan The table 'tbl' is fullketika Anda melebihi batas memori MySQL). Empat jenis pilih yang saya lihat adalah:

  1. PILIH vanilla
  2. penting
  3. SELECT bersyarat
  4. sub-seleks yang diindeks dan tidak diindeks

Pertama, saya membuat tiga tabel menggunakan SQL berikut

CREATE TABLE
    data_interrogation.test_table_myisam
    (
        index_col BIGINT NOT NULL AUTO_INCREMENT,
        value1 DOUBLE,
        value2 DOUBLE,
        value3 DOUBLE,
        value4 DOUBLE,
        PRIMARY KEY (index_col)
    )
    ENGINE=MyISAM DEFAULT CHARSET=utf8

dengan 'MyISAM' menggantikan 'InnoDB' dan 'memori' di tabel kedua dan ketiga.

 

1) Vanilla memilih

Pertanyaan: SELECT * FROM tbl WHERE index_col = xx

Hasil: menggambar

Perbandingan pemilihan vanili oleh mesin basis data yang berbeda

Kecepatannya semua sama, dan seperti yang diharapkan adalah linier dalam jumlah kolom yang akan dipilih. InnoDB tampaknya sedikit lebih cepat daripada MyISAM tetapi ini benar-benar marjinal.

Kode:

import timeit
import MySQLdb
import MySQLdb.cursors
import random
from random import randint

db = MySQLdb.connect(host="...", user="...", passwd="...", db="...", cursorclass=MySQLdb.cursors.DictCursor)
cur = db.cursor()

lengthOfTable = 100000

# Fill up the tables with random data
for x in xrange(lengthOfTable):
    rand1 = random.random()
    rand2 = random.random()
    rand3 = random.random()
    rand4 = random.random()

    insertString = "INSERT INTO test_table_innodb (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"
    insertString2 = "INSERT INTO test_table_myisam (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"
    insertString3 = "INSERT INTO test_table_memory (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"

    cur.execute(insertString)
    cur.execute(insertString2)
    cur.execute(insertString3)

db.commit()

# Define a function to pull a certain number of records from these tables
def selectRandomRecords(testTable,numberOfRecords):

    for x in xrange(numberOfRecords):
        rand1 = randint(0,lengthOfTable)

        selectString = "SELECT * FROM " + testTable + " WHERE index_col = " + str(rand1)
        cur.execute(selectString)

setupString = "from __main__ import selectRandomRecords"

# Test time taken using timeit
myisam_times = []
innodb_times = []
memory_times = []

for theLength in [3,10,30,100,300,1000,3000,10000]:

    innodb_times.append( timeit.timeit('selectRandomRecords("test_table_innodb",' + str(theLength) + ')', number=100, setup=setupString) )
    myisam_times.append( timeit.timeit('selectRandomRecords("test_table_myisam",' + str(theLength) + ')', number=100, setup=setupString) )
    memory_times.append( timeit.timeit('selectRandomRecords("test_table_memory",' + str(theLength) + ')', number=100, setup=setupString) )

 

2) Hitungan

Pertanyaan: SELECT count(*) FROM tbl

Hasil: MyISAM menang

Perbandingan jumlah dengan mesin database yang berbeda

Yang ini menunjukkan perbedaan besar antara MyISAM dan InnoDB - MyISAM (dan memori) melacak jumlah catatan dalam tabel, sehingga transaksi ini cepat dan O (1). Jumlah waktu yang diperlukan untuk InnoDB untuk menghitung meningkat secara super-linear dengan ukuran tabel dalam kisaran yang saya selidiki. Saya menduga banyak percepatan dari pertanyaan MyISAM yang diamati dalam praktek adalah karena efek yang sama.

Kode:

myisam_times = []
innodb_times = []
memory_times = []

# Define a function to count the records
def countRecords(testTable):

    selectString = "SELECT count(*) FROM " + testTable
    cur.execute(selectString)

setupString = "from __main__ import countRecords"

# Truncate the tables and re-fill with a set amount of data
for theLength in [3,10,30,100,300,1000,3000,10000,30000,100000]:

    truncateString = "TRUNCATE test_table_innodb"
    truncateString2 = "TRUNCATE test_table_myisam"
    truncateString3 = "TRUNCATE test_table_memory"

    cur.execute(truncateString)
    cur.execute(truncateString2)
    cur.execute(truncateString3)

    for x in xrange(theLength):
        rand1 = random.random()
        rand2 = random.random()
        rand3 = random.random()
        rand4 = random.random()

        insertString = "INSERT INTO test_table_innodb (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"
        insertString2 = "INSERT INTO test_table_myisam (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"
        insertString3 = "INSERT INTO test_table_memory (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"

        cur.execute(insertString)
        cur.execute(insertString2)
        cur.execute(insertString3)

    db.commit()

    # Count and time the query
    innodb_times.append( timeit.timeit('countRecords("test_table_innodb")', number=100, setup=setupString) )
    myisam_times.append( timeit.timeit('countRecords("test_table_myisam")', number=100, setup=setupString) )
    memory_times.append( timeit.timeit('countRecords("test_table_memory")', number=100, setup=setupString) )

 

3) Pilihan kondisional

Pertanyaan: SELECT * FROM tbl WHERE value1<0.5 AND value2<0.5 AND value3<0.5 AND value4<0.5

Hasil: MyISAM menang

Perbandingan pilihan kondisional oleh mesin basis data yang berbeda

Di sini, MyISAM dan memori melakukan kira-kira sama, dan mengalahkan InnoDB sekitar 50% untuk tabel yang lebih besar. Ini adalah jenis permintaan yang manfaat MyISAM tampaknya dimaksimalkan.

Kode:

myisam_times = []
innodb_times = []
memory_times = []

# Define a function to perform conditional selects
def conditionalSelect(testTable):
    selectString = "SELECT * FROM " + testTable + " WHERE value1 < 0.5 AND value2 < 0.5 AND value3 < 0.5 AND value4 < 0.5"
    cur.execute(selectString)

setupString = "from __main__ import conditionalSelect"

# Truncate the tables and re-fill with a set amount of data
for theLength in [3,10,30,100,300,1000,3000,10000,30000,100000]:

    truncateString = "TRUNCATE test_table_innodb"
    truncateString2 = "TRUNCATE test_table_myisam"
    truncateString3 = "TRUNCATE test_table_memory"

    cur.execute(truncateString)
    cur.execute(truncateString2)
    cur.execute(truncateString3)

    for x in xrange(theLength):
        rand1 = random.random()
        rand2 = random.random()
        rand3 = random.random()
        rand4 = random.random()

        insertString = "INSERT INTO test_table_innodb (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"
        insertString2 = "INSERT INTO test_table_myisam (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"
        insertString3 = "INSERT INTO test_table_memory (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"

        cur.execute(insertString)
        cur.execute(insertString2)
        cur.execute(insertString3)

    db.commit()

    # Count and time the query
    innodb_times.append( timeit.timeit('conditionalSelect("test_table_innodb")', number=100, setup=setupString) )
    myisam_times.append( timeit.timeit('conditionalSelect("test_table_myisam")', number=100, setup=setupString) )
    memory_times.append( timeit.timeit('conditionalSelect("test_table_memory")', number=100, setup=setupString) )

 

4) Sub-pilih

Hasil: InnoDB menang

Untuk kueri ini, saya membuat satu set tabel tambahan untuk sub-pilih. Masing-masing hanya dua kolom BIGINTs, satu dengan indeks kunci utama dan satu tanpa indeks apa pun. Karena ukuran meja yang besar, saya tidak menguji mesin memori. Perintah pembuatan tabel SQL adalah

CREATE TABLE
    subselect_myisam
    (
        index_col bigint NOT NULL,
        non_index_col bigint,
        PRIMARY KEY (index_col)
    )
    ENGINE=MyISAM DEFAULT CHARSET=utf8;

di mana sekali lagi, 'MyISAM' diganti untuk 'InnoDB' di tabel kedua.

Dalam kueri ini, saya meninggalkan ukuran tabel pemilihan pada 1000000 dan sebagai gantinya memvariasikan ukuran kolom yang dipilih.

Perbandingan sub-seleksi oleh berbagai mesin basis data

Di sini InnoDB menang dengan mudah. Setelah kita sampai ke tabel ukuran yang wajar, kedua mesin skala linear dengan ukuran sub-pilih. Indeks mempercepat perintah MyISAM tetapi menarik tidak banyak berpengaruh pada kecepatan InnoDB. subSelect.png

Kode:

myisam_times = []
innodb_times = []
myisam_times_2 = []
innodb_times_2 = []

def subSelectRecordsIndexed(testTable,testSubSelect):
    selectString = "SELECT * FROM " + testTable + " WHERE index_col in ( SELECT index_col FROM " + testSubSelect + " )"
    cur.execute(selectString)

setupString = "from __main__ import subSelectRecordsIndexed"

def subSelectRecordsNotIndexed(testTable,testSubSelect):
    selectString = "SELECT * FROM " + testTable + " WHERE index_col in ( SELECT non_index_col FROM " + testSubSelect + " )"
    cur.execute(selectString)

setupString2 = "from __main__ import subSelectRecordsNotIndexed"

# Truncate the old tables, and re-fill with 1000000 records
truncateString = "TRUNCATE test_table_innodb"
truncateString2 = "TRUNCATE test_table_myisam"

cur.execute(truncateString)
cur.execute(truncateString2)

lengthOfTable = 1000000

# Fill up the tables with random data
for x in xrange(lengthOfTable):
    rand1 = random.random()
    rand2 = random.random()
    rand3 = random.random()
    rand4 = random.random()

    insertString = "INSERT INTO test_table_innodb (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"
    insertString2 = "INSERT INTO test_table_myisam (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"

    cur.execute(insertString)
    cur.execute(insertString2)

for theLength in [3,10,30,100,300,1000,3000,10000,30000,100000]:

    truncateString = "TRUNCATE subselect_innodb"
    truncateString2 = "TRUNCATE subselect_myisam"

    cur.execute(truncateString)
    cur.execute(truncateString2)

    # For each length, empty the table and re-fill it with random data
    rand_sample = sorted(random.sample(xrange(lengthOfTable), theLength))
    rand_sample_2 = random.sample(xrange(lengthOfTable), theLength)

    for (the_value_1,the_value_2) in zip(rand_sample,rand_sample_2):
        insertString = "INSERT INTO subselect_innodb (index_col,non_index_col) VALUES (" + str(the_value_1) + "," + str(the_value_2) + ")"
        insertString2 = "INSERT INTO subselect_myisam (index_col,non_index_col) VALUES (" + str(the_value_1) + "," + str(the_value_2) + ")"

        cur.execute(insertString)
        cur.execute(insertString2)

    db.commit()

    # Finally, time the queries
    innodb_times.append( timeit.timeit('subSelectRecordsIndexed("test_table_innodb","subselect_innodb")', number=100, setup=setupString) )
    myisam_times.append( timeit.timeit('subSelectRecordsIndexed("test_table_myisam","subselect_myisam")', number=100, setup=setupString) )

    innodb_times_2.append( timeit.timeit('subSelectRecordsNotIndexed("test_table_innodb","subselect_innodb")', number=100, setup=setupString2) )
    myisam_times_2.append( timeit.timeit('subSelectRecordsNotIndexed("test_table_myisam","subselect_myisam")', number=100, setup=setupString2) )

Saya pikir pesan yang bisa dibawa pulang dari semua ini adalah bahwa jika Anda benar - benar peduli tentang kecepatan, Anda perlu membandingkan permintaan yang Anda lakukan daripada membuat asumsi tentang mesin mana yang lebih cocok.

StackG
sumber
1
kinerja tidak selalu menjadi satu-satunya pertimbangan, bagaimana dengan grafik tentang stabilitas? mesin tidak baik untuk apa pun jika crash dan tidak mendukung fitur basis data dasar.
pilavdzice
1
MyISAM mungkin akan mengalahkan InnoDB sebagian besar kali jika my.cnffile tidak dioptimalkan untuk InnoDB. Anda belum menyebutkan bagaimana my.cnffile Anda terlihat, yang sebenarnya merupakan faktor paling penting untuk kinerja InnoDB.
itoctopus
Terima kasih itoctopus - Saya ingin mendengar lebih banyak tentang optimasi yang Anda rekomendasikan. Kode lengkap yang digunakan dalam tes ini di atas, jangan ragu untuk mengulangi percobaan dengan berbagai optimisasi dan beri tahu kami jika Anda menemukan perubahan signifikan dalam hasilnya
StackG
32

Agak di luar topik, tetapi untuk tujuan dokumentasi dan kelengkapan, saya ingin menambahkan yang berikut ini.

Secara umum menggunakan InnoDB akan menghasilkan banyak aplikasi yang kompleks KURANG, mungkin juga lebih bebas bug. Karena Anda dapat memasukkan semua integritas referensial (batasan Kunci Asing) ke dalam model data, Anda tidak perlu mendekati kode aplikasi sebanyak yang Anda perlukan dengan MyISAM.

Setiap kali Anda memasukkan, menghapus, atau mengganti catatan, Anda HARUS memeriksa dan memelihara hubungan. Misalnya, jika Anda menghapus orangtua, semua anak juga harus dihapus. Misalnya, bahkan dalam sistem blogging sederhana, jika Anda menghapus catatan blogposting, Anda harus menghapus catatan komentar, suka, dll. Di InnoDB ini dilakukan secara otomatis oleh mesin database (jika Anda menentukan batasan dalam model ) dan tidak memerlukan kode aplikasi. Dalam MyISAM ini harus dikodekan ke dalam aplikasi, yang sangat sulit di server web. Server web pada dasarnya sangat konkuren / paralel dan karena tindakan ini harus bersifat atomis dan MyISAM tidak mendukung transaksi nyata, menggunakan MyISAM untuk server web berisiko / rawan kesalahan.

Juga dalam kebanyakan kasus umum, InnoDB akan melakukan jauh lebih baik, karena berbagai alasan, salah satunya mereka dapat menggunakan penguncian tingkat rekor sebagai lawan penguncian tingkat-tabel. Tidak hanya dalam situasi di mana menulis lebih sering daripada membaca, juga dalam situasi dengan penggabungan kompleks pada dataset besar. Kami melihat peningkatan kinerja 3 kali lipat hanya dengan menggunakan tabel InnoDB di atas tabel MyISAM untuk penggabungan yang sangat besar (mengambil beberapa menit).

Saya akan mengatakan bahwa secara umum InnoDB (menggunakan datamodel 3NF lengkap dengan integritas referensial) harus menjadi pilihan default saat menggunakan MySQL. MyISAM hanya boleh digunakan dalam kasus yang sangat spesifik. Ini kemungkinan besar akan melakukan lebih sedikit, menghasilkan aplikasi yang lebih besar dan lebih buggy.

Setelah mengatakan ini. Datamodelling adalah seni yang jarang ditemukan di antara desainer web / program. Jangan tersinggung, tetapi itu menjelaskan MyISAM sedang digunakan begitu banyak.

Patrick Savalle
sumber
31

InnoDB menawarkan:

ACID transactions
row-level locking
foreign key constraints
automatic crash recovery
table compression (read/write)
spatial data types (no spatial indexes)

Di InnoDB semua data berturut-turut kecuali TEXT dan BLOB dapat menempati paling banyak 8.000 byte Pengindeksan teks lengkap tidak tersedia untuk InnoDB. Di InnoDB, COUNT (*) s (ketika WHERE, GROUP BY, atau JOIN tidak digunakan) mengeksekusi lebih lambat daripada di MyISAM karena jumlah baris tidak disimpan secara internal. InnoDB menyimpan data dan indeks dalam satu file. InnoDB menggunakan kumpulan buffer untuk menyimpan data dan indeks.

MyISAM menawarkan:

fast COUNT(*)s (when WHERE, GROUP BY, or JOIN is not used)
full text indexing
smaller disk footprint
very high table compression (read only)
spatial data types and indexes (R-tree)

MyISAM memiliki penguncian level-tabel, tetapi tidak ada penguncian level-baris. Tidak ada transaksi. Tidak ada pemulihan kerusakan otomatis, tetapi memang menawarkan fungsionalitas tabel perbaikan. Tidak ada batasan kunci asing. Tabel MyISAM umumnya lebih kompak dalam ukuran pada disk jika dibandingkan dengan tabel InnoDB. Tabel MyISAM dapat semakin diperkecil ukurannya dengan mengompresi dengan myisampack jika diperlukan, tetapi menjadi read-only. MyISAM menyimpan indeks dalam satu file dan data di file lain. MyISAM menggunakan buffer kunci untuk indeks caching dan membiarkan manajemen caching data ke sistem operasi.

Secara keseluruhan saya akan merekomendasikan InnoDB untuk sebagian besar keperluan dan MyISAM hanya untuk penggunaan khusus. InnoDB sekarang menjadi mesin default di versi MySQL baru.

Pankaj Khurana
sumber
2
fwiw, VARCHAR di InnoDB juga bisa masuk ke halaman melimpah, seperti BLOB dan TEXT do. Semua tipe data ini disimpan secara internal.
Bill Karwin
Senang tahu, @BillKarwin! Kami banyak menggunakan VARCHAR di aplikasi kami dan memiliki VARCHAR berkontribusi pada batas ~ 8kB ini sedikit memprihatinkan.
rinogo
Lihat mysqlperformanceblog.com/2010/02/09/blob-storage-in-innodb untuk rincian lebih lanjut.
Bill Karwin
jawaban tidak up to date sebagai mesin innodb di MySQL versi 5.6+ saat ini juga mendukung pengindeksan teks lengkap dan juga MySQL 5.5 + / 5.7 + mendukung tipe data spasial (5.5+) dan indeks spasial (r-tee) (5.7+) .. Untuk dukungan terbaik, Anda setidaknya harus memiliki MySQL versi 5.7+
Raymond Nijland
25

Jika Anda menggunakan MyISAM, Anda tidak akan melakukan transaksi apa pun per jam, kecuali jika Anda menganggap setiap pernyataan DML sebagai transaksi (yang dalam hal apa pun, tidak akan tahan lama atau bersifat atom jika terjadi kerusakan).

Karena itu saya pikir Anda harus menggunakan InnoDB.

300 transaksi per detik sepertinya cukup banyak. Jika Anda benar-benar membutuhkan transaksi ini agar tahan lama saat terjadi kegagalan daya, pastikan subsistem I / O Anda dapat menangani banyak penulisan ini per detik dengan mudah. Anda memerlukan setidaknya pengontrol RAID dengan cache yang didukung baterai.

Jika Anda dapat mengambil daya tahan yang kecil, Anda dapat menggunakan InnoDB dengan innodb_flush_log_at_trx_commit diatur ke 0 atau 2 (lihat dokumen untuk detail), Anda dapat meningkatkan kinerja.

Ada sejumlah tambalan yang dapat meningkatkan konkurensi dari Google dan lainnya - ini mungkin menarik jika Anda masih tidak bisa mendapatkan kinerja yang cukup tanpa mereka.

MarkR
sumber
24

Pertanyaan dan sebagian besar Jawaban sudah ketinggalan zaman .

Ya, itu adalah kisah istri lama bahwa MyISAM lebih cepat dari InnoDB. perhatikan tanggal Pertanyaan: 2008; sekarang hampir satu dekade kemudian. InnoDB telah membuat langkah kinerja yang signifikan sejak saat itu.

Grafik dramatis adalah untuk satu kasus di mana MyISAM menang: COUNT(*) tanpa sebuah WHEREklausa. Tetapi apakah itu benar-benar apa yang Anda habiskan untuk melakukan?

Jika Anda menjalankan uji konkurensi , InnoDB sangat mungkin menang, bahkan melawanMEMORY .

Jika Anda melakukan penulisan apa pun saat melakukan tolok ukur SELECTs, MyISAM dan MEMORYkemungkinan akan hilang karena penguncian tingkat-tabel.

Faktanya, Oracle sangat yakin bahwa InnoDB lebih baik sehingga mereka menghapus MyISAM dari 8.0.

The Pertanyaan ditulis di awal hari-hari 5.1. Sejak itu, versi-versi utama ini ditandai "Ketersediaan Umum":

  • 2010: 5.5 (.8 pada Desember)
  • 2013: 5.6 (.10 pada bulan Februari)
  • 2015: 5.7 (.9 pada Oktober)
  • 2018: 8.0 (.11 pada bulan April)

Intinya: Jangan gunakan MyISAM

Rick James
sumber
2
Kemajuan teknologi database MySQL. Dan pertanyaan dan jawaban StackOverflow tetap terperosok di masa lalu. Perbedaan utama antara MyISAM dan InnoDB adalah lebih sedikit tentang "memuat" di server, dan lebih banyak tentang dukungan untuk integritas referensial dan transaksi , serta konkurensi dan pemulihan (+10)
spencer7593
12

Periksa juga penggantian drop-in untuk MySQL itu sendiri:

MariaDB

http://mariadb.org/

MariaDB adalah server database yang menawarkan fungsionalitas penggantian drop-in untuk MySQL. MariaDB dibangun oleh beberapa penulis asli MySQL, dengan bantuan dari komunitas pengembang perangkat lunak bebas dan sumber terbuka yang lebih luas. Selain fungsionalitas inti MySQL, MariaDB menawarkan serangkaian peningkatan fitur termasuk mesin penyimpanan alternatif, optimisasi server, dan tambalan.

Server Percona

https://launchpad.net/percona-server

Pengganti drop-in yang disempurnakan untuk MySQL, dengan kinerja yang lebih baik, diagnostik yang ditingkatkan, dan fitur yang ditambahkan.

Refiner
sumber
1
Saya menggunakan keduanya (Percona dalam produksi, Maria pada pengembangan windows). mereka lebih cepat dan bekerja dengan sempurna.
Moshe L
4
Ini tidak menjawab pertanyaan. MariaDB dan Percona adalah fork dari MySQL, dan menggunakan mesin InnoDB dan MyISAM juga.
dr_
12

Harap dicatat bahwa pendidikan dan pengalaman formal saya adalah dengan Oracle, sementara pekerjaan saya dengan MySQL sepenuhnya bersifat pribadi dan berdasarkan waktu saya sendiri, jadi jika saya mengatakan hal-hal yang benar untuk Oracle tetapi tidak berlaku untuk MySQL, saya minta maaf. Meskipun kedua sistem memiliki banyak hal, teori / aljabar relasional adalah sama, dan basis data relasional masih merupakan basis data relasional, masih ada banyak perbedaan !!

Saya terutama suka (dan juga penguncian tingkat baris) bahwa InnoDB berbasis transaksi, yang berarti bahwa Anda mungkin memperbarui / memasukkan / membuat / mengubah / menjatuhkan / dll beberapa kali untuk satu "operasi" aplikasi web Anda. Masalah yang muncul adalah bahwa jika hanya beberapa dari perubahan / operasi tersebut yang akhirnya dilakukan, tetapi yang lain tidak, Anda akan sering kali (tergantung pada desain spesifik dari database) berakhir dengan database dengan data / struktur yang saling bertentangan.

Catatan: Dengan Oracle, buat / ubah / lepas pernyataan yang disebut "DDL" (Data Definition) pernyataan, dan secara implisit memicu komit. Sisipkan / perbarui / hapus pernyataan, yang disebut "DML" (Manipulasi Data), tidak dilakukan secara otomatis, tetapi hanya ketika DDL, komit, atau keluar / keluar dilakukan (atau jika Anda mengatur sesi Anda untuk "komit otomatis", atau jika klien Anda melakukan komitmen secara otomatis). Sangat penting untuk menyadari hal itu ketika bekerja dengan Oracle, tetapi saya tidak yakin bagaimana MySQL menangani dua jenis pernyataan. Karena itu, saya ingin memperjelas bahwa saya tidak yakin tentang ini ketika datang ke MySQL; hanya dengan Oracle.

Contoh saat mesin berbasis transaksi unggul:

Katakanlah saya atau Anda berada di halaman web untuk mendaftar untuk menghadiri acara gratis, dan salah satu tujuan utama sistem ini adalah hanya mengizinkan hingga 100 orang untuk mendaftar, karena itu adalah batas tempat duduk untuk acara tersebut. Setelah 100 pendaftaran tercapai, sistem akan menonaktifkan pendaftaran lebih lanjut, setidaknya sampai yang lain membatalkan.

Dalam hal ini, mungkin ada tabel untuk tamu (nama, telepon, email, dll.), Dan tabel kedua yang melacak jumlah tamu yang telah mendaftar. Dengan demikian kami memiliki dua operasi untuk satu "transaksi". Sekarang anggaplah bahwa setelah info tamu ditambahkan ke tabel TAMU, ada kehilangan koneksi, atau kesalahan dengan dampak yang sama. Tabel GUESTS diperbarui (dimasukkan ke dalam), tetapi koneksi terputus sebelum "kursi yang tersedia" dapat diperbarui.

Sekarang kami memiliki tamu yang ditambahkan ke tabel tamu, tetapi jumlah kursi yang tersedia sekarang salah (misalnya, nilainya 85 ketika sebenarnya 84).

Tentu saja ada banyak cara untuk menangani hal ini, seperti melacak kursi yang tersedia dengan "100 dikurangi jumlah baris di tabel tamu," atau beberapa kode yang memeriksa bahwa informasinya konsisten, dll .... Tetapi dengan basis data berbasis transaksi mesin seperti InnoDB, baik SEMUA operasi dilakukan, atau TIDAK ADA dari mereka. Ini dapat membantu dalam banyak kasus, tetapi seperti yang saya katakan, ini bukan cara HANYA untuk aman, tidak (cara yang baik, bagaimanapun, ditangani oleh database, bukan programmer / penulis naskah).

Itu semua "berbasis transaksi" pada dasarnya berarti dalam konteks ini, kecuali jika saya kehilangan sesuatu - bahwa seluruh transaksi berhasil sebagaimana mestinya, atau tidak ada yang berubah, karena hanya membuat perubahan parsial yang dapat membuat sedikit ke BEBERAPA kekacauan dari database, bahkan mungkin merusaknya ...

Tapi saya akan mengatakannya sekali lagi, itu bukan satu-satunya cara untuk menghindari kekacauan. Tetapi itu adalah salah satu metode yang ditangani oleh mesin itu sendiri, meninggalkan Anda ke kode / skrip dengan hanya perlu khawatir tentang "apakah transaksi berhasil atau tidak, dan apa yang saya lakukan jika tidak (seperti coba lagi)," alih-alih secara manual menulis kode untuk memeriksanya "secara manual" dari luar basis data, dan melakukan lebih banyak pekerjaan untuk acara semacam itu.

Terakhir, catatan tentang penguncian tabel vs penguncian baris:

PENOLAKAN: Saya mungkin salah dalam semua yang mengikuti sehubungan dengan MySQL, dan situasi hipotetis / contoh adalah hal-hal yang perlu diperhatikan, tetapi saya mungkin salah dalam apa yang sebenarnya mungkin menyebabkan korupsi dengan MySQL. Contoh-contohnya sangat nyata dalam pemrograman umum, bahkan jika MySQL memiliki lebih banyak mekanisme untuk menghindari hal-hal seperti itu ...

Pokoknya, saya cukup percaya diri dalam menyetujui dengan mereka yang berpendapat bahwa berapa banyak koneksi yang diperbolehkan pada suatu waktu tidak tidak bekerja di sekitar meja terkunci. Faktanya, banyak koneksi adalah tujuan utama mengunci meja !! Sehingga proses / pengguna / aplikasi lain tidak dapat merusak database dengan membuat perubahan pada saat bersamaan.

Bagaimana dua atau lebih koneksi yang bekerja pada baris yang sama akan membuat Anda benar-benar buruk? Misalkan ada dua proses yang keduanya ingin / perlu memperbarui nilai yang sama di baris yang sama, katakanlah karena baris tersebut adalah catatan tur bus, dan masing-masing dari dua proses secara bersamaan ingin memperbarui "pengendara" atau "available_seats" bidang sebagai "nilai saat ini ditambah 1."

Mari kita lakukan ini secara hipotesis, langkah demi langkah:

  1. Proses satu membaca nilai saat ini, katakanlah itu kosong, dengan demikian '0' sejauh ini.
  2. Proses dua membaca nilai saat ini juga, yang masih 0.
  3. Proses satu menulis (saat ini + 1) yaitu 1.
  4. Proses dua harus menulis 2, tetapi karena membaca nilai saat ini sebelum proses satu menulis nilai baru, itu juga menulis 1 ke tabel.

Saya tidak yakin bahwa dua koneksi dapat berbaur seperti itu, keduanya membaca sebelum yang pertama menulis ... Tetapi jika tidak, maka saya masih akan melihat masalah dengan:

  1. Proses satu membaca nilai saat ini, yaitu 0.
  2. Proses satu menulis (saat ini +1), yaitu 1.
  3. Proses dua membaca nilai saat ini sekarang. Tetapi saat memproses satu penulisan DID (pembaruan), ia belum melakukan data, sehingga hanya proses yang sama yang dapat membaca nilai baru yang diperbarui, sementara yang lainnya melihat nilai yang lebih lama, hingga ada komit.

Juga, setidaknya dengan database Oracle, ada tingkat isolasi, yang tidak akan saya buang-buang waktu untuk mencoba parafrase. Berikut ini adalah artikel yang bagus tentang hal itu, dan setiap tingkat isolasi memiliki pro dan kontra, yang akan sejalan dengan betapa pentingnya mesin berbasis transaksi dalam database ...

Terakhir, kemungkinan ada perlindungan yang berbeda di dalam MyISAM, alih-alih kunci asing dan interaksi berbasis transaksi. Yah, untuk satu, ada fakta bahwa seluruh tabel terkunci, yang membuatnya lebih kecil kemungkinan bahwa transaksi / FK diperlukan .

Dan sayangnya, jika Anda mengetahui masalah konkurensi ini, ya Anda bisa memainkannya dengan kurang aman dan cukup menulis aplikasi Anda, atur sistem Anda sehingga kesalahan semacam itu tidak mungkin (kode Anda bertanggung jawab, bukan database itu sendiri). Namun, menurut pendapat saya, saya akan mengatakan bahwa selalu terbaik untuk menggunakan perlindungan sebanyak mungkin, pemrograman secara defensif, dan selalu menyadari bahwa kesalahan manusia tidak mungkin untuk dihindari sepenuhnya. Itu terjadi pada semua orang, dan siapa pun yang mengatakan mereka kebal terhadapnya pasti berbohong, atau belum melakukan lebih dari menulis aplikasi / skrip "Hello World". ;-)

Saya berharap bahwa BEBERAPA dari itu bermanfaat bagi seseorang, dan bahkan lebih-lebih, saya berharap bahwa saya belum menjadi pelakunya asumsi dan menjadi manusia yang salah !! Saya minta maaf jika demikian, tetapi contoh-contohnya bagus untuk dipikirkan, meneliti risiko, dan sebagainya, bahkan jika mereka tidak berpotensi dalam konteks spesifik ini.

Jangan ragu untuk mengoreksi saya, edit "jawaban" ini, bahkan berikan suara. Coba saja perbaiki, daripada mengoreksi asumsi saya yang buruk dengan yang lain. ;-)

Ini adalah tanggapan pertama saya, jadi tolong maafkan panjang lebar karena semua penafian, dll ... Saya hanya tidak ingin terdengar sombong ketika saya tidak benar-benar yakin!

Arembjorn
sumber
5

Dalam pengalaman saya, MyISAM adalah pilihan yang lebih baik selama Anda tidak melakukan DELETEs, UPDATEs, banyak sekali INSERT tunggal, transaksi, dan pengindeksan teks lengkap. BTW, CHECK TABLE mengerikan. Saat tabel bertambah tua dalam hal jumlah baris, Anda tidak tahu kapan akan berakhir.

yogman
sumber
2
Pengindeksan teks lengkap hanya dimungkinkan dengan MyISAM, bukan dengan InnoDB.
Pixel Elephant
2
@ PixelElephant, itu mulai berubah di MySQL 5.6. InnoDB memiliki tipe indeks fulltext, tetapi sejauh ini agak tidak siap untuk digunakan produksi IMHO.
Bill Karwin
1
“Pengindeksan teks lengkap hanya dimungkinkan dengan MyISAM, bukan dengan InnoDB”: tidak ada yang lebih benar sejak MySQL> = 5.6. Lihat dev.mysql.com/doc/refman/5.6/en/fulltext-search.html .
Hibou57
5

Saya telah mengetahui bahwa meskipun Myisam memiliki pendapat penguncian, itu masih lebih cepat daripada InnoDb di sebagian besar skenario karena skema akuisisi kunci cepat yang digunakannya. Saya sudah mencoba beberapa kali Innodb dan selalu kembali ke MyIsam karena satu dan lain alasan. InnoDB juga bisa menjadi sangat intensif CPU dalam banyak menulis.

Ricardo
sumber
4

Setiap aplikasi memiliki profil kinerja sendiri untuk menggunakan database, dan kemungkinan itu akan berubah seiring waktu.

Hal terbaik yang dapat Anda lakukan adalah menguji opsi Anda. Beralih antara MyISAM dan InnoDB adalah sepele, jadi muat beberapa data uji dan jalankan jmeter ke situs Anda dan lihat apa yang terjadi.

Gary Richardson
sumber
4

Saya mencoba menjalankan penyisipan data acak ke dalam tabel MyISAM dan InnoDB. Hasilnya cukup mengejutkan. MyISAM membutuhkan beberapa detik lebih sedikit untuk memasukkan 1 juta baris daripada InnoDB hanya 10 ribu!

pengguna965748
sumber
2
Anda akan mendapatkan kinerja yang sama, jika Anda menggunakan transaksi dan mematikan autocommit untuk mesin InnoDB.
stanleyxu2005
IDK jika kinerjanya sama, tapi itulah yang saya lakukan di aplikasi yang lebih kompleks dan itu mempercepatnya.
user965748
1
Anda gagal memberikan detail persis percobaan Anda - pengaturan konfigurasi mana? Apa yang ada di tabel sebelumnya? Jenis data apa? dan mungkin yang paling penting - apakah ada sisipan berurutan? Paralel? Apa waktu mereka? Berapa core CPU? Utas? dll
einpoklum
3

myisam adalah NOGO untuk jenis beban kerja (menulis concurrency tinggi), saya tidak punya banyak pengalaman dengan innodb (mengujinya 3 kali dan menemukan dalam setiap kasus bahwa kinerja tersedot, tetapi sudah lama sejak tes terakhir) jika Anda Saya tidak dipaksa untuk menjalankan mysql, pertimbangkan untuk mencoba postgres karena ia menangani bersamaan menulis JAUH lebih baik

pfote
sumber
3

Singkatnya, InnoDB bagus jika Anda mengerjakan sesuatu yang membutuhkan database yang dapat diandalkan yang dapat menangani banyak instruksi INSERT dan UPDATE.

dan, MyISAM baik jika Anda membutuhkan database yang sebagian besar akan mengambil banyak instruksi baca (SELECT) daripada menulis (INSERT dan PEMBARUAN), mengingat kelemahannya pada hal kunci-tabel.

Anda mungkin ingin check out;
Pro dan Kontra InnoDB
Pro dan Kontra dari MyISAM

Light93
sumber
2

Saya tahu ini tidak akan populer tetapi begini:

myISAM tidak memiliki dukungan untuk esensi basis data seperti transaksi dan integritas referensial yang sering menghasilkan aplikasi yang bermasalah / bermasalah. Anda tidak dapat tidak mempelajari dasar-dasar desain database yang tepat jika mereka bahkan tidak didukung oleh mesin db Anda.

Tidak menggunakan integritas referensial atau transaksi dalam dunia basis data seperti tidak menggunakan pemrograman berorientasi objek dalam dunia perangkat lunak.

InnoDB ada sekarang, gunakan itu! Bahkan pengembang MySQL akhirnya mengakui untuk mengubahnya ke mesin default di versi yang lebih baru, meskipun myISAM menjadi mesin asli yang merupakan default di semua sistem warisan.

Tidak masalah jika Anda membaca atau menulis atau pertimbangan kinerja apa yang Anda miliki, menggunakan myISAM dapat menyebabkan berbagai masalah, seperti yang baru saja saya temui: Saya melakukan sinkronisasi basis data dan pada saat yang sama orang lain mengakses aplikasi yang mengakses tabel yang diatur ke myISAM. Karena kurangnya dukungan transaksi dan keandalan mesin yang buruk, ini membuat seluruh database lumpuh dan saya harus me-restart mysql secara manual!

Selama 15 tahun terakhir pengembangan saya telah menggunakan banyak database dan mesin. myISAM menabrak saya sekitar belasan kali selama periode ini, database lain, hanya sekali! Dan itu adalah database SQL microsoft di mana beberapa pengembang menulis kode CLR yang salah (runtime bahasa umum - pada dasarnya kode C # yang dieksekusi di dalam database) omong-omong, itu bukan kesalahan mesin database sebenarnya.

Saya setuju dengan jawaban lain di sini yang mengatakan bahwa kualitas tinggi ketersediaan, aplikasi berkinerja tinggi tidak boleh menggunakan myISAM karena tidak akan bekerja, itu tidak kuat atau cukup stabil untuk menghasilkan pengalaman bebas frustrasi. Lihat jawaban Bill Karwin untuk lebih jelasnya.

PS Harus suka kalau fanboys myISAM saya memilih tetapi tidak bisa memberi tahu Anda bagian mana dari jawaban ini yang salah.

pilavdzice
sumber
5
Saya tidak downvote, tetapi jika saya lakukan itu untuk menasihati tidak pernah digunakan. kata itu tidak seharusnya ditulis dalam kosakata pengembang ... peringatan menjadi 'tidak pernah mengatakan tidak pernah'.
hubson bropa
1

Untuk itu rasio baca / tulis saya kira InnoDB akan tampil lebih baik. Karena Anda baik-baik saja dengan pembacaan yang kotor, Anda mungkin (jika mampu) mereplikasi ke budak dan membiarkan semua bacaan Anda pergi ke budak. Juga, pertimbangkan untuk memasukkan secara massal, bukan satu rekaman pada satu waktu.

aise neal
sumber
1

Hampir setiap kali saya memulai proyek baru saya Google pertanyaan yang sama ini untuk melihat apakah saya menemukan jawaban baru.

Akhirnya bermuara pada - Saya mengambil versi terbaru dari MySQL dan menjalankan tes.

Saya punya tabel di mana saya ingin melakukan pencarian kunci / nilai ... dan itu saja. Saya perlu mendapatkan nilai (0-512 byte) untuk kunci hash. Tidak banyak transaksi pada DB ini. Tabel mendapat pembaruan sesekali (secara keseluruhan), tetapi 0 transaksi.

Jadi kita tidak berbicara tentang sistem yang rumit di sini, kita berbicara tentang pencarian sederhana, .. dan bagaimana (selain membuat tabel RAM penduduk) kita dapat mengoptimalkan kinerja.

Saya juga melakukan tes pada database lain (yaitu NoSQL) untuk melihat apakah ada tempat saya bisa mendapatkan keuntungan. Keuntungan terbesar yang saya temukan adalah dalam pemetaan kunci tetapi sejauh pencarian, MyISAM saat ini memuncaki semuanya.

Meskipun, saya tidak akan melakukan transaksi keuangan dengan tabel MyISAM tetapi untuk pencarian sederhana, Anda harus mengujinya .. biasanya 2x hingga 5x kueri / detik.

Ujilah, saya menyambut debat.

Cyberwip
sumber
1

Jika sisipan 70% dan 30% dibaca maka itu lebih seperti di sisi InnoDB.

kta
sumber
0

bottomline: jika Anda bekerja offline dengan memilih potongan data yang besar, MyISAM mungkin akan memberi Anda kecepatan yang lebih baik (lebih baik).

ada beberapa situasi ketika MyISAM jauh lebih efisien daripada InnoDB: ketika memanipulasi data dump besar secara offline (karena kunci tabel).

contoh: Saya mengonversi file csv (catatan 15M) dari NOAA yang menggunakan bidang VARCHAR sebagai kunci. InnoDB mengambil selamanya, bahkan dengan banyak memori yang tersedia.

ini adalah contoh csv (bidang pertama dan ketiga adalah kunci).

USC00178998,20130101,TMAX,-22,,,7,0700
USC00178998,20130101,TMIN,-117,,,7,0700
USC00178998,20130101,TOBS,-28,,,7,0700
USC00178998,20130101,PRCP,0,T,,7,0700
USC00178998,20130101,SNOW,0,T,,7,

karena apa yang perlu saya lakukan adalah menjalankan pembaruan offline batch fenomena cuaca yang diamati, saya menggunakan tabel MyISAM untuk menerima data dan menjalankan GABUNGAN pada tombol sehingga saya dapat membersihkan file yang masuk dan mengganti bidang VARCHAR dengan kunci INT (yang terkait dengan tabel eksternal tempat nilai VARCHAR asli disimpan).

tony gil
sumber