886

私は、多くのデータベース書き込みを伴うプロジェクトに取り組んでいます ( 70% の挿入と 30% の読み取り)。この比率には、1 回の読み取りと 1 回の書き込みと見なされる更新も含まれます。読み取りはダーティになる可能性があります (たとえば、読み取り時に 100% 正確な情報は必要ありません)。
問題のタスクは、1 時間に 100 万を超えるデータベース トランザクションを実行することになります。

MyISAM と InnoDB の違いについて Web でたくさん読んだことがありますが、このタスクに使用する特定のデータベース/テーブルには MyISAM が当然の選択のようです。私が読んでいるように見えることから、行レベルのロックがサポートされているため、トランザクションが必要な場合は InnoDB が適しています。

このタイプの負荷 (またはそれ以上) の経験がある人はいますか? MyISAM は進むべき道ですか?

4

25 に答える 25

538

InnoDBMyISAMのどちらを使用するかを結論付けることができるように、この質問について表で簡単に説明しました。

以下は、どの状況でどの db ストレージ エンジンを使用する必要があるかについての簡単な概要です。

                                                 MyISAM InnoDB
-------------------------------------------------- --------------
必須の全文検索 はい 5.6.4
-------------------------------------------------- --------------
トランザクションが必要 はい
-------------------------------------------------- --------------
頻繁な選択クエリ はい      
-------------------------------------------------- --------------
頻繁な挿入、更新、削除 はい
-------------------------------------------------- --------------
行ロック(単一テーブルでのマルチ処理) あり
-------------------------------------------------- --------------
リレーショナル ベース設計 はい

概要

  • ほとんどすべての状況で、InnoDBが最善の方法です
  • ただし、頻繁に読む、ほとんど書くことがない、MyISAMを使用する
  • MySQL <= 5.5 での全文検索、MyISAMを使用
于 2011-07-22T22:01:34.190 に答える
270

私はデータベースの専門家ではありませんし、経験から話すこともありません。でも:

MyISAM テーブルは、テーブル レベルのロックを使用します。トラフィックの見積もりに基づくと、毎秒 200 近くの書き込みがあります。MyISAM を使用すると、いつでも進行できるのはこれらのうちの 1 つだけです。オーバーランを避けるために、ハードウェアがこれらのトランザクションに対応できることを確認する必要があります。つまり、1 つのクエリに 5 ミリ秒以上かかることはありません。

これは、行レベルのロックをサポートするストレージ エンジン、つまり InnoDB が必要であることを示唆しています。

一方、いくつかの簡単なスクリプトを記述して各ストレージ エンジンの負荷をシミュレートし、結果を比較するのはかなり簡単です。

于 2008-08-22T16:03:00.493 に答える
198

人々はパフォーマンス、読み取りと書き込み、外部キーなどについてよく話しますが、私の考えでは、ストレージ エンジンにはもう 1 つ必須の機能があり ます。それは、アトミックな更新です。

これを試して:

  1. MyISAM テーブルに対して 5 秒かかる UPDATE を発行します。
  2. UPDATE の進行中、たとえば 2.5 秒後に Ctrl-C を押して中断します。
  3. テーブルへの影響を観察します。更新された行数は? 更新されなかったのはいくつですか? テーブルは読み取り可能ですか、それとも Ctrl-C を押したときに破損していましたか?
  4. 進行中のクエリを中断して、InnoDB テーブルに対して UPDATE で同じ実験を試してください。
  5. InnoDB テーブルを観察します。 ゼロ行が更新されました。InnoDB は、アトミックな更新があることを保証しており、完全な更新をコミットできなかった場合は、変更全体をロールバックします。また、テーブルは破損していません。killall -9 mysqldこれは、 を使用してクラッシュをシミュレートする場合でも機能します。

もちろん、パフォーマンスは望ましいものですが、データを失わないことがそれよりも重要です。

于 2013-07-17T17:47:27.607 に答える
138

私は MySQL を使用して大量のシステムに取り組み、MyISAM と InnoDB の両方を試しました。

MyISAM のテーブル レベルのロックが、ワークロードに深刻なパフォーマンス上の問題を引き起こしていることがわかりました。残念ながら、InnoDB でのパフォーマンスも期待していたよりも悪いことがわかりました。

最後に、挿入が「ホット」テーブルに入り、選択がホット テーブルをクエリしないようにデータを断片化することで、競合の問題を解決しました。

これにより、選択クエリによって再び触れられなかった「古い」テーブルで削除が発生することもありました (データは時間に敏感で、X 日間の価値しか保持していませんでした)。InnoDB は一括削除のパフォーマンスが低いように見えるため、データのパージを計画している場合は、古いデータが古いテーブルにあるように構造化して、削除を実行する代わりに簡単に削除できるようにすることをお勧めします。

もちろん、あなたのアプリケーションが何であるかはわかりませんが、MyISAM と InnoDB に関するいくつかの問題についての洞察が得られることを願っています。

于 2008-09-16T21:57:00.183 に答える
68

ゲームには少し遅れています...しかし、これは私が数ヶ月前に書いた非常に包括的な投稿で、MYISAMとInnoDBの主な違いを詳述しています。カップパ (そしておそらくビスケット) を手に取り、お楽しみください。


MyISAM と InnoDB の主な違いは、参照整合性とトランザクションにあります。ロック、ロールバック、全文検索など、他にも違いがあります。

参照整合性

参照整合性により、テーブル間の関係の一貫性が保たれます。より具体的には、これは、テーブル (例: Listings) が別のテーブル (例: Products) を指す外部キー (例: Product ID) を持っている場合、更新または削除がポイント先のテーブルに発生した場合、これらの変更がリンクにカスケードされることを意味します。テーブル。この例では、製品の名前が変更されると、リンク テーブルの外部キーも更新されます。製品が「製品」テーブルから削除された場合、削除されたエントリを参照するすべてのリストも削除されます。さらに、新しいリストには、有効な既存のエントリを指す外部キーが必要です。

InnoDB はリレーショナル DBMS (RDBMS) であるため、参照整合性がありますが、MyISAM にはありません。

トランザクションと原子性

テーブル内のデータは、SELECT、INSERT、UPDATE、DELETE などのデータ操作言語 (DML) ステートメントを使用して管理されます。トランザクションは、2 つ以上の DML ステートメントを 1 つの作業単位にグループ化するため、単位全体が適用されるか、まったく適用されないかのいずれかになります。

MyISAM はトランザクションをサポートしていませんが、InnoDB はサポートしています。

MyISAM テーブルの使用中に操作が中断された場合、操作はすぐに中止され、影響を受ける行 (または各行内のデータ) は、操作が完了していなくても影響を受け続けます。

InnoDB テーブルの使用中に操作が中断された場合、原子性を持つトランザクションを使用しているため、コミットが行われないため、完了に至らなかったトランザクションは有効になりません。

テーブルロックと行ロック

MyISAM テーブルに対してクエリを実行すると、クエリを実行しているテーブル全体がロックされます。これは、現在のクエリが終了した後にのみ、後続のクエリが実行されることを意味します。大きなテーブルを読み取っている場合、および/または頻繁な読み取りおよび書き込み操作がある場合、これはクエリの膨大なバックログを意味する可能性があります。

クエリが InnoDB テーブルに対して実行されると、関連する行のみがロックされ、テーブルの残りの部分は CRUD 操作に使用できます。これは、クエリが同じ行を使用しない限り、同じテーブルで同時に実行できることを意味します。

InnoDB のこの機能は、同時実行性として知られています。同時実行性が優れているのと同様に、選択した範囲のテーブルに適用される大きな欠点があります。カーネル スレッド間の切り替えにはオーバーヘッドがあり、サーバーが停止しないようにカーネル スレッドに制限を設定する必要があります。 .

トランザクションとロールバック

MyISAM で操作を実行すると、変更が設定されます。InnoDB では、これらの変更をロールバックできます。トランザクションを制御するために使用される最も一般的なコマンドは、COMMIT、ROLLBACK、および SAVEPOINT です。1. COMMIT - 複数の DML 操作を記述できますが、変更は COMMIT が行われたときにのみ保存されます 2. ROLLBACK - まだコミットされていない操作を破棄できます 3. SAVEPOINT - リスト内のポイントを設定しますROLLBACK 操作でロールバックできる操作

信頼性

MyISAM はデータの整合性を提供しません。ハードウェアの障害、クリーンでないシャットダウン、およびキャンセルされた操作により、データが破損する可能性があります。これには、インデックスとテーブルの完全な修復または再構築が必要です。

一方、InnoDB は、トランザクション ログ、二重書き込みバッファ、および自動チェックサムと検証を使用して、破損を防ぎます。InnoDB は変更を行う前に、トランザクション前のデータを ibdata1 というシステム テーブルスペース ファイルに記録します。クラッシュが発生した場合、InnoDB はそれらのログの再生を通じて自動回復します。

FULLTEXT インデックス作成

InnoDB は、MySQL バージョン 5.6.4 までは FULLTEXT インデックス作成をサポートしていません。この投稿の執筆時点では、多くの共有ホスティング プロバイダーの MySQL バージョンはまだ 5.6.4 未満です。つまり、InnoDB テーブルでは FULLTEXT インデックス作成がサポートされていません。

ただし、これは MyISAM を使用する正当な理由ではありません。最新バージョンの MySQL をサポートするホスティング プロバイダーに変更することをお勧めします。FULLTEXT インデックスを使用する MyISAM テーブルを InnoDB テーブルに変換できないわけではありません。

結論

結論として、InnoDB をデフォルトのストレージ エンジンとして選択する必要があります。特定のニーズを満たす場合は、MyISAM またはその他のデータ タイプを選択します。

于 2015-01-21T15:32:33.573 に答える
64

より多くの書き込みと読み取りを伴う負荷の場合、InnoDB のメリットが得られます。InnoDB はテーブル ロックではなく行ロックを提供するため、SELECT複数の s を相互に同時実行できるだけでなく、多数INSERTの s と同時実行することもできます。ただし、SQL トランザクションを使用する予定がない場合は、 InnoDB コミット フラッシュを 2 に設定します ( innodb_flush_log_at_trx_commit )。これにより、テーブルを MyISAM から InnoDB に移動するときに失われてしまう多くの生のパフォーマンスが得られます。

また、レプリケーションを追加することも検討してください。これにより、ある程度の読み取りスケーリングが可能になり、読み取りが最新である必要はないと述べたので、レプリケーションを少し遅らせることができます。交通量が最も多い場合を除いて、追いつくことができることを確認してください。そうしないと、常に遅れて追いつくことはありません. ただし、この方法を使用する場合は、スレーブからの読み取りとレプリケーション ラグ管理をデータベース ハンドラーに分離することを強くお勧めします。アプリケーション コードがこれを認識していない場合は、非常に簡単です。

最後に、さまざまなテーブル ロードに注意してください。すべてのテーブルで読み取り/書き込み比率が同じになるわけではありません。ほぼ 100% の読み取りを行ういくつかの小さなテーブルは、MyISAM のままにしておく余裕があります。同様に、書き込み率が 100% に近いテーブルがいくつかある場合は、 の恩恵を受ける可能性がありますがINSERT DELAYED、これは MyISAM でのみサポートされています (このDELAYED節は InnoDB テーブルでは無視されます)。

しかし、確かにベンチマーク。

于 2009-01-05T23:39:39.357 に答える
60

2 つのエンジンの機械的な違いをカバーする応答の幅広い選択に追加するために、経験的な速度比較研究を提示します。

純粋な速度に関しては、MyISAM が InnoDB より速いとは限りませんが、私の経験では、PURE READ 作業環境では約 2.0 倍から 2.5 倍高速になる傾向があります。明らかに、これはすべての環境に適しているわけではありません - 他の人が書いているように、MyISAM にはトランザクションや外部キーなどが欠けています。

以下で少しベンチマークを行いました。ループには python を使用し、タイミング比較には timeit ライブラリを使用しました。興味深いことに、メモリ エンジンも含めました。これにより、ボード全体で最高のパフォーマンスが得られますが、小さなテーブルにのみ適しています ( The table 'tbl' is fullMySQL のメモリ制限を超えた場合に頻繁に遭遇します)。私が見ている選択の4つのタイプは次のとおりです。

  1. バニラSELECT
  2. 数えます
  3. 条件付きSELECT
  4. 索引付きおよび索引なしの副選択

まず、次のSQLを使用して3つのテーブルを作成しました

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

2 番目と 3 番目のテーブルで、'InnoDB' と 'memory' を 'MyISAM' に置き換えます。

 

1) バニラセレクト

クエリ:SELECT * FROM tbl WHERE index_col = xx

結果:引き分け

さまざまなデータベース エンジンによるバニラの選択の比較

これらの速度はすべてほぼ同じであり、予想どおり、選択される列の数に比例します。InnoDB はMyISAM よりわずかに速いように見えますが、これは実際にはわずかです。

コード:

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) カウント

クエリ:SELECT count(*) FROM tbl

結果: MyISAM が勝利

異なるデータベース エンジンによるカウントの比較

これは、MyISAM と InnoDB の大きな違いを示しています。MyISAM (およびメモリ) はテーブル内のレコード数を追跡するため、このトランザクションは高速で O(1) です。InnoDB がカウントするのに必要な時間は、調査した範囲のテーブル サイズに応じて非常に直線的に増加します。実際に観察された MyISAM クエリの高速化の多くは、同様の効果によるものだと思います。

コード:

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) 条件選択

クエリ:SELECT * FROM tbl WHERE value1<0.5 AND value2<0.5 AND value3<0.5 AND value4<0.5

結果: MyISAM が勝利

異なるデータベース エンジンによる条件選択の比較

ここでは、MyISAM とメモリはほぼ同じパフォーマンスを発揮し、より大きなテーブルでは InnoDB を約 50% 上回っています。これは、MyISAM の利点が最大化されていると思われる種類のクエリです。

コード:

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) サブセレクト

結果: InnoDB が勝利

このクエリでは、サブセレクト用に追加のテーブル セットを作成しました。それぞれが BIGINT の単純な 2 つの列であり、一方には主キー インデックスがあり、もう一方にはインデックスがありません。テーブルのサイズが大きいため、メモリ エンジンはテストしませんでした。SQL テーブル作成コマンドは

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

ここでも、2 番目のテーブルの「InnoDB」が「MyISAM」に置き換えられます。

このクエリでは、選択テーブルのサイズを 1000000 のままにし、代わりにサブ選択された列のサイズを変更します。

異なるデータベース エンジンによるサブセレクトの比較

ここでは、InnoDB が簡単に勝ちます。適切なサイズのテーブルに到達すると、両方のエンジンがサブセレクトのサイズに比例してスケーリングします。インデックスは MyISAM コマンドを高速化しますが、興味深いことに InnoDB の速度にはほとんど影響しません。subSelect.png

コード:

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) )

これらすべての重要なメッセージは、速度を本当に気にしている場合は、どのエンジンがより適しているかを推測するのではなく、実行しているクエリをベンチマークする必要があるということです。

于 2015-06-11T09:15:31.813 に答える
33

少しトピックから外れていますが、ドキュメントの目的と完全性のために、以下を追加したいと思います。

一般に、InnoDB を使用すると、アプリケーションの複雑さが大幅に軽減され、おそらくバグもなくなります。すべての参照整合性 (外部キー制約) をデータモデルに入れることができるため、MyISAM で必要なほど多くのアプリケーション コードは必要ありません。

レコードを挿入、削除、または置換するたびに、関係を確認して維持する必要があります。たとえば、親を削除する場合、すべての子も削除する必要があります。たとえば、単純なブログ システムでも、ブログ投稿レコードを削除すると、コメント レコードやいいねなどを削除する必要があります。 InnoDB では、これはデータベース エンジンによって自動的に行われます (モデルで制約を指定した場合)。 ) であり、アプリケーション コードは必要ありません。MyISAM では、これをアプリケーションにコーディングする必要がありますが、これは Web サーバーでは非常に困難です。Web サーバーは本質的に非常に並行/並列であり、これらのアクションはアトミックである必要があり、MyISAM は実際のトランザクションをサポートしていないため、Web サーバーに MyISAM を使用することはリスクが高く、エラーが発生しやすくなります。

また、ほとんどの一般的なケースでは、テーブル レベルのロックではなくレコード レベルのロックを使用できるという複数の理由により、InnoDB のパフォーマンスが大幅に向上します。書き込みが読み取りよりも頻繁に行われる状況だけでなく、大規模なデータセットで複雑な結合が行われる状況でも。非常に大規模な結合 (数分かかる) では、MyISAM テーブルよりも InnoDB テーブルを使用するだけで、パフォーマンスが 3 倍向上することに気付きました。

一般に、MySQL を使用する場合は、InnoDB (参照整合性を備えた 3NF データモデルを使用) をデフォルトの選択肢にする必要があります。MyISAM は、非常に特殊な場合にのみ使用してください。ほとんどの場合、パフォーマンスが低下し、より大きくてバグのあるアプリケーションになります。

これを言った。データモデリングは、Web デザイナーやプログラマーの間ではめったに見られない技術です。問題はありませんが、MyISAM が非常に多く使用されていることは説明できます。

于 2012-08-26T12:18:07.053 に答える
31

InnoDB は以下を提供します。

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

InnoDB では、TEXT と BLOB を除く行内のすべてのデータは、最大で 8,000 バイトを占めることができます。InnoDB では、全文索引は使用できません。InnoDB では、COUNT(*) (WHERE、GROUP BY、または JOIN が使用されていない場合) は MyISAM よりも低速で実行されます。これは、行カウントが内部に格納されていないためです。InnoDB は、データとインデックスの両方を 1 つのファイルに格納します。InnoDB はバッファ プールを使用して、データとインデックスの両方をキャッシュします。

MyISAM が提供するもの:

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 にはテーブル レベルのロックがありますが、行レベルのロックはありません。取引はありません。自動クラッシュ リカバリはありませんが、修復テーブル機能を提供します。外部キー制約なし。InnoDB テーブルと比較すると、MyISAM テーブルは通常、ディスク上のサイズがコンパクトです。MyISAM テーブルは、必要に応じて myisampack で圧縮することでサイズをさらに大幅に縮小できますが、読み取り専用になります。MyISAM はインデックスを 1 つのファイルに保存し、データを別のファイルに保存します。MyISAM はインデックスのキャッシュにキー バッファーを使用し、データ キャッシュの管理はオペレーティング システムに任せます。

全体として、ほとんどの目的には InnoDB を、特別な用途には MyISAM をお勧めします。InnoDB は、新しい MySQL バージョンのデフォルト エンジンになりました。

于 2013-05-28T07:03:17.287 に答える
25

MyISAM を使用する場合、各 DML ステートメントをトランザクションと見なさない限り、1 時間あたりのトランザクションは発生しません (いずれにせよ、クラッシュが発生した場合、永続的またはアトミックではありません)。

したがって、InnoDB を使用する必要があると思います。

1 秒あたり 300 回のトランザクションは、かなりの量に思えます。これらのトランザクションが停電後も持続することが絶対に必要な場合は、I/O サブシステムが 1 秒あたりの書き込み数を簡単に処理できることを確認してください。バッテリでバックアップされたキャッシュを備えた RAID コントローラが少なくとも 1 つ必要です。

耐久性にわずかな影響を与えることができる場合は、innodb_flush_log_at_trx_commit を 0 または 2 に設定して InnoDB を使用できます (詳細についてはドキュメントを参照してください)。パフォーマンスを向上させることができます。

Google などから、同時実行性を向上させるパッチが多数提供されています。パッチなしでは十分なパフォーマンスが得られない場合は、これらのパッチが役立つ可能性があります。

于 2008-09-16T21:34:54.137 に答える
25

質問と回答のほとんどは古くなっています

はい、MyISAM が InnoDB よりも高速であるというのは老婆の話です。質問の日付に注意してください: 2008; ほぼ10年後の今です。それ以来、InnoDB はパフォーマンスを大幅に向上させました。

劇的なグラフは、MyISAM が勝つ 1 つのケース (節COUNT(*) なし)のものです。WHEREしかし、それは本当にあなたが時間を費やしていることですか?

並行性テストを実行すると、InnoDB が勝つ可能性が非常に高くなりますMEMORY

ベンチマーク中に書き込みを行うSELECTsと、MyISAM とMEMORYテーブル レベルのロックが原因で失われる可能性があります。

実際、Oracle は InnoDB の方が優れていると確信しているため、MyISAM を 8.0 からほぼすべて削除しました。

Questionは 5.1の初期に書かれました。それ以降、これらのメジャー バージョンは「一般提供」とマークされました。

  • 2010年: 5.5 (12月は.8)
  • 2013年: 5.6 (2月は.10)
  • 2015年: 5.7 (10月は.9)
  • 2018年: 8.0 (4月は.11)

結論: MyISAM を使用しないでください

于 2017-05-03T18:26:39.687 に答える
12

また、MySQL 自体のいくつかのドロップイン置換も確認してください。

マリアDB

http://mariadb.org/

MariaDB は、MySQL のドロップイン代替機能を提供するデータベース サーバーです。MariaDB は、MySQL のオリジナルの作成者の何人かによって構築されており、フリーおよびオープン ソース ソフトウェア開発者の幅広いコミュニティからの支援を受けています。MySQL のコア機能に加えて、MariaDB は、代替ストレージ エンジン、サーバーの最適化、およびパッチを含む豊富な機能拡張セットを提供します。

ペルコナサーバー

https://launchpad.net/percona-server

優れたパフォーマンス、改善された診断、および追加機能を備えた、MySQL の強化されたドロップイン代替品です。

于 2012-04-03T15:49:40.167 に答える
11

これは、違いと、どちらを使用する必要があるかを説明する優れた記事だと思います: http://tag1consulting.com/MySQL_Engines_MyISAM_vs_InnoDB

于 2010-08-20T22:15:32.657 に答える
5

私の経験では、DELETE、UPDATE、大量の単一INSERT、トランザクション、およびフルテキストインデックス作成を行わない限り、MyISAMの方が適していました。ところで、チェックテーブルはひどいです。テーブルは行数の点で古くなるので、いつ終了するかわかりません。

于 2009-01-06T00:14:42.890 に答える
5

Myisam にはロックの競合がありますが、使用する高速ロック取得スキームにより、ほとんどのシナリオで InnoDb よりも高速であることがわかりました。私は Innodb を数回試しましたが、何らかの理由で常に MyIsam に戻ります。また、InnoDB は、大量の書き込み負荷がかかると、CPU を非常に集中的に使用する可能性があります。

于 2010-09-14T09:27:00.673 に答える
4

MyISAMテーブルとInnoDBテーブルにランダムデータの挿入を実行しようとしました。結果は非常に衝撃的でした。MyISAMは、わずか1万のInnoDBよりも100万行を挿入するのに数秒少なくて済みました。

于 2011-11-24T00:34:25.427 に答える
4

すべてのアプリケーションには、データベースを使用するための独自のパフォーマンス プロファイルがあり、時間の経過とともに変化する可能性があります。

あなたができる最善のことは、オプションをテストすることです。MyISAM と InnoDB の切り替えは簡単なので、テスト データをロードし、サイトに対して jmeter を起動して、何が起こるかを確認してください。

于 2008-08-22T17:07:16.330 に答える
3

myisam は、そのタイプのワークロード (高同時書き込み) の NOGO です。私は innodb の経験があまりありません (3 回テストし、いずれの場合もパフォーマンスが悪いことがわかりましたが、前回のテストからしばらく時間が経っています)。 'mysql の実行を強制されていません。postgres を試してみることを検討してください。同時書き込みがはるかにうまく処理されます

于 2009-10-31T10:21:32.517 に答える
3

要するに、InnoDB は、多くの INSERT および UPDATE 命令を処理できる信頼性の高いデータベースを必要とする作業をしている場合に適しています。

また、MyISAM は、テーブル ロックに関する欠点を考慮して、書き込み (INSERT および UPDATES) ではなく、多くの読み取り (SELECT) 命令を実行するデータベースが必要な場合に適しています。

チェックアウトすることをお勧めします。
InnoDB の
長所と短所 MyISAM の長所と短所

于 2015-02-08T16:54:37.237 に答える
1

挿入が 70% で読み取りが 30% の場合は、InnoDB 側に似ています。

于 2013-12-14T03:08:05.597 に答える
1

その読み取り/書き込みの比率については、InnoDB のパフォーマンスが向上すると思います。ダーティ リードは問題ないので、(余裕が​​あれば) スレーブにレプリケートし、すべての読み取りをスレーブに任せることができます。また、一度に 1 つのレコードではなく、一括して挿入することを検討してください。

于 2010-07-05T15:51:58.347 に答える
1

新しいプロジェクトを始めるたびに、この同じ質問を Google で検索して、新しい答えが得られるかどうかを確認します。

最終的には、MySQL の最新バージョンを使用してテストを実行します。

キー/値のルックアップを行いたいテーブルがあります...それだけです。ハッシュ キーの値 (0 ~ 512 バイト) を取得する必要があります。この DB には多くのトランザクションはありません。テーブルは時々 (全体として) 更新されますが、トランザクションは 0 です。

したがって、ここでは複雑なシステムについて話しているのではなく、単純なルックアップについて話している..そして (テーブル RAM を常駐させる以外に) パフォーマンスを最適化する方法について話している。

また、他のデータベース (NoSQL など) でテストを行って、利点を得ることができる場所があるかどうかを確認しています。私が見つけた最大の利点はキー マッピングにありますが、ルックアップに関する限り、現在 MyISAM がすべてを上回っています。

とはいえ、MyISAM テーブルを使用して金融取引を実行するつもりはありませんが、単純なルックアップについては、テストする必要があります..通常、1 秒あたりのクエリの 2 倍から 5 倍です。

テストしてください。議論を歓迎します。

于 2013-08-20T07:54:48.777 に答える