MyISAM対InnoDB [終了]


857

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

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

このタイプの負荷(またはそれ以上)の経験はありますか?MyISAMを使用する方法はありますか?


13
MySQLのパフォーマンスのブログは事のこのタイプのための素晴らしいリソースです。
ceejayoz 2008

3
これは、システムがOLTPであるか、それともデータウェアハウス指向であるか(ほとんどの書き込みがバルクロードである場合)によって多少異なります。
nos

35
MyISAMは行ロック、トランザクション、外部キーさえもサポートしていません... ACIDを提供できないため、適切なデータベースと見なすこともできません。これが、MySQL 5.5以降InnoDBがデフォルトのエンジンである理由です...しかし、何らかの理由で、MyISAMは引き続きPhpMyAdmin内で作成されたテーブルのデフォルトエンジンであるため、多くのアマチュアデータベースがMyISAMで実行されています。
BlueRaja-Danny Pflughoeft 2013年


回答:


523

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

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

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

概要

  • ほとんどすべての状況で、InnoDBが最善の方法です
  • しかし、頻繁に読んで、ほとんど書かず、MyISAMを使用します
  • MySQLでの全文検索<= 5.5、MyISAMを使用

11
MySQL 5.6にはInnoDBのフルテキストインデックスがありますが、これまでのところ、実際に使用する準備は整っていません。
Bill Karwin 2013

3
アコード12.9。フルテキスト検索機能、「フルテキストインデックスはInnoDBまたはMyISAMテーブルでのみ使用できます」。MySQL> = 5.6では問題ないようですが、MySQL 5.5の同じページには、「フルテキストインデックスはMyISAMテーブルでのみ使用できます」とまだ記載されています。上記の表は、MySQLのバージョンによってどのように異なるかを示すように更新できます。残念ながら、これまでのところ、MySQL 5.5が標準のようです。
Hibou57 2013

2
の意味は何InnoDB - full-text: 5.6.4ですか?はいかどうか?

2
MyISAMは行数も内部に格納します。したがって、Count()関数はMyISAMではほとんど無料ですが、InnoDBではかなり時間がかかります。
Hedeshy

3
良いテーブルですが、品質と安定性のために行を追加します。MyIsam= no、innoDB = yesならさらに良くなります
pilavdzice

268

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

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

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

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


12
200近く?彼の平均取引は2.5クエリを行った場合、その者の[(2.5 * 1M)/ 3600 =]近い700に
オジー

12
またa single query can take no more than 5ms、あなたが2つのありそうもない仮定をしたので、私も同意しません。A:すべてのクエリで同じテーブルが必要でした&B:使用できる接続は1つだけでした!高いRAMを備えたLinuxとMySQL 5.5のセットアップは最大10,000の同時接続をサポートできることをお知らせします(参照:dev.mysql.com/doc/refman//5.5/en/too-many-connections.html
オジー

152
テーブルがロックされている場合、一度に実行できるクエリは1つだけです。サーバーが10000の同時接続をサポートしているかどうかは関係ありません。それぞれがテーブルがロックされている間にバックアップします。
Ryaner 2012

2
また、MyISAMは空間インデックスをサポートしていますが、InnoDBはサポートしていないことを知っておくと役立ちます。MyISAMは外部キーの作成を妨げていませんが、外部キーを使用していないようです。
kriver

4
@kriver:MyISAMテーブルに外部キーを含めることはできません。CREATE TABLEステートメントにFK定義を含めることができますが、それら(定義)は単に無視されます。
ypercubeᵀᴹ

191

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

これを試して:

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

もちろんパフォーマンスは望ましいですが、データ失うことはそれよりも優先されます。


4
記録としては、ACIDデータベースの他の特性(一貫性、分離、および耐久性)もMyISAMではサポートされていません。
ビルカーウィン、2014年

Control-Cがテーブルを破損しないようにする必要があります。CHECKTABLEは成功を返し、すべてのクエリはエラーなしで続行されます。MyISAMはすべてのレコードを更新せずに更新を中止しますが、テーブルは内部構造の整合性を維持します。mysqldをSIGTERMで強制終了しても同じ効果があります。ただし、SIGKILL(kill -9)または何らかのクラッシュ信号(または、バグに遭遇するとそれ自体でそれを獲得する)を与えた場合、またはOSがクラッシュ/電源が失われた場合、それは別の話です-あなたは見ることができますMyISAMレベルの破損。
Sasha Pachev

1
InnoDBは、王室にもそれ自体を破壊する可能性があり、通常はMyISAMよりも王室に破壊されます。ACIDの皮肉なのは、私たちには全部かゼロかの概念があるということです。したがって、InnoDBがすべてを与えることができない場合、それは何も与えません-内部アサート、および何らかの構造の1バイトが間違っているために実行をまったく拒否します-時間の90%は無視され、最大で1つのテーブルのみに影響します。最近のPerconaサーバーには、それに対処するオプションがあります-innodb_pass_corrupt_table。
Sasha Pachev

1
私は過去3日間にこの種の情報を検索していましたが、これを取得しました。InnoDBが最適です。ありがとうBill Karwin
user3833682

3
@ flow2k、最近はほとんどありません。私の最後の仕事では、1台のサーバーの1つのテーブルにMyISAMを使用しましたが、唯一の理由は、MyISAMがその特定のテーブルをInnoDBが持つよりも少ないスペースに格納できることでした。ディスク容量に制約があったため、データベースを別のサーバーに移動できるようになるまでMyISAMを使用する必要がありました。私の新しい仕事では、すべてのテーブルがInnoDBでなければならないというポリシーがすでにあります。
Bill Karwin 2017

138

私はMySQLを使用して大容量システムで作業し、MyISAMとInnoDBの両方を試しました。

MyISAMのテーブルレベルのロックにより、私たちのワークロードに深刻なパフォーマンスの問題が発生し、あなたと同じように聞こえることがわかりました。残念ながら、私はまた、InnoDBでのパフォーマンスも期待していたよりも悪いことがわかりました。

最後に、挿入を「ホット」テーブルに入れ、ホットテーブルをクエリしないようにデータをフラグメント化することで、競合の問題を解決しました。

これにより、選択クエリによって変更されなかった「古くなった」テーブルで削除(データは時間依存であり、X日間の価値しか保持しませんでした)も可能になりました。InnoDBは一括削除でのパフォーマンスが低いようです。そのため、データのパージを計画している場合は、古いデータが古いテーブルにあり、削除を実行するのではなく単に削除できる古いテーブルにあるようにデータを構造化することができます。

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


3
「最後に、私は、インサートは、ホットテーブルを照会したことがない『ホット』表と選択に入ったようなデータを断片化することにより、競合の問題を解決する「。 -基本的にどのようなことではありませんバッファプールが?のためである
BlueRaja -ダニーPflughoeft

15
ダニー-いいえ、そうでもない。サーバー設定のチューニングは重要ですが、スキーマの慎重な構造化に代わるものではありません。利用可能なRAMよりはるかに大きいDBと、DB全体のデータにランダムにアクセスするアクセスパターンがある場合、世界中のすべてのバッファープールの調整は役に立ちません。データとアクセスパターンを理解していれば、注意深く設計することで、痛みの多くを軽減できます。
alanc10n 2013年

66

ゲームには少し遅れますが、MYISAMとInnoDBの主な違いを詳しく説明した、数か月前に書いた非常に包括的な投稿です。クッパ(そしておそらくビスケット)をつかんで、楽しんでください。


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

参照整合性

参照整合性により、テーブル間の関係の一貫性が維持されます。より具体的には、これは、テーブル(例:リスト)が別のテーブル(例:製品)を指す外部キー(例:製品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はそれらのログの再生を通じて自動復旧します。

フルテキストインデックス

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

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

結論

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


私はphpセッションチェックサムスクリプトを作成しており、私のキーのほとんどは[az09]のランダムな文字列です... Innodbは30ミリ秒以上かかったINSERT ON DUPLICATE KEY UPDATEので、MyISAMを試してみましたが、1ミリ秒未満になりました... innodbは、「ソートできない」(ランダムな文字列)一意のキーを処理するのに苦労します...その上で何か入力はありますか?実際、MyISAMを使用しなければならない影響について疑問に思っていましたが、あなたの素晴らしい答えは、それがその特定のケースに進むための方法だと気づかせてくれました。
Louis Loudog Trottier

64

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

また、レプリケーションの追加を検討してください。これにより、読み取りのスケーリングが得られます。読み取りは最新である必要はないと述べたので、レプリケーションを少し遅らせることができます。最も重いトラフィック以外では追いつくことができるか、常に遅れて追いつくことがないことを確認してください。ただし、この方法を使用する場合は、スレーブからの読み取りとレプリケーションラグ管理をデータベースハンドラーに分離することを強くお勧めします。アプリケーションコードがこれを知らなければ、それはとても簡単です。

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

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


4
あなたが参照する「InnoDBコミットフラッシュ」はありますinnodb_flush_log_at_trx_commitか?
ceejayoz

2
あなたの投稿はとても役に立ちました-ありがとう。MyISAM / InnoDBをテーブルにいつ使用するかを評価しているところと、あなたの投稿は役に立ちました。乾杯。
starmonkey

2
dev.mysql.com/doc/refman/5.5/en/insert-delayed.html状態:MyISAMテーブルの場合、データファイルの途中に空きブロックがない場合、同時のSELECTおよびINSERTステートメントがサポートされます。このような状況では、MyISAMでINSERT DELAYEDを使用する必要はほとんどありません。
チムタム2009

非常に有益な投稿。私はオペレーションと同じ質問がありました、そしてあなたの投稿が私のデータベースエンジンの決定について私を安心させてくれたと言わざるを得ません。ありがとう!++
Joe Majewski 2012

クイックノート:5.7ではdelayはサポートされなくなりました。代わりに、LOW_PRIORITYを使用してテストすることもできます。
webmat 2014

59

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

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

以下のベンチマークを少し行いました。ループにはpythonを使用し、タイミング比較にはtimeitライブラリを使用しました。興味深いことに、私はメモリエンジンも含めました。これは、全体的に最高のパフォーマンスを提供しThe table 'tbl' is fullますが、小さなテーブルにのみ適しています(MySQLメモリの制限を超えると、常に発生します)。私が見るselectの4つのタイプは:

  1. バニラセレクト
  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」と「メモリ」の代わりに「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つの列であり、1つは主キーインデックスがあり、もう1つはインデックスがありません。テーブルサイズが大きいため、メモリエンジンはテストしませんでした。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) )

これらすべての要点は、速度に本当に関心がある場合は、どのエンジンがより適切であるかを想定するのではなく、実行しているクエリをベンチマークする必要があるということです。


1
常に考慮しなければならないのはパフォーマンスだけではありません。安定性に関するグラフはどうでしょうか。エンジンがクラッシュし、基本的なデータベース機能をサポートしない場合、エンジンは何にも適していません。
pilavdzice 2016年

1
my.cnfファイルがInnoDB用に最適化されていない場合、MyISAMはおそらくほとんどの場合InnoDBを上回るでしょう。あなたはあなたのmy.cnfファイルがどのように見えるかについて言及していません。これはInnoDBのパフォーマンスにとって本当に最も重要な要素です。
itoctopus 2017年

itoctopusに感謝-あなたが推奨する最適化についてもっと知りたいです。これらのテストで使用されている完全なコードは上記のとおりです。さまざまな最適化を行って実験を繰り返し、結果に大きな変化を見つけた場合はお知らせください
StackG

32

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

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

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

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

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

これを言った。データモデリングは、ウェブデザイナーやプログラマーの間ではめったに見られない芸術です。違反はありませんが、MyISAMが非常に使用されていることを説明しています。


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

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


2
fwiw、InnoDBのVARCHARもBLOBやTEXTのようにオーバーフローページに移動できます。これらすべてのデータ型は、内部的に同様に保存されます。
ビルカーウィン2013

知っておくと良いこと、@ BillKarwin!私たちはアプリでVARCHARを頻繁に使用し、VARCHARがこの〜8kBの制限に貢献することは少し心配でした。
rinogo 2013年

詳細については、mysqlperformanceblog.com / 2010/02/09 / blob-storage-in-innodbを参照してください。
Bill Karwin 2013年

MySQLバージョン5.6以降のinnodbエンジンは現在、フルテキストインデックス作成もサポートしており、MySQL 5.5以降は、空間データタイプ(5.5以降)空間インデックス(r-tee)(5.7以降)をサポートしているため、答えは最新ではありません。..最良のサポートを得るには、少なくともMySQLバージョン5.7以降が必要です
Raymond Nijland

25

あなたはMyISAMテーブルを使用している場合、あなたはやってません任意のあなたは、各DML文は(どのような場合には、クラッシュが発生した場合に、耐久性やアトミックではありません)取引であると考えていない限り、時間あたりのトランザクションを。

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

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

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

Googleや他のユーザーからの同時実行性を高めることができるパッチがいくつかあります。これらのパッチがないと十分なパフォーマンスが得られない場合は、これらのパッチが興味深いかもしれません。


24

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

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

:劇的なグラフは、MyISAMテーブルが勝っ1ケースのためだっCOUNT(*) ずにWHERE句。しかし、それは本当にあなたが時間を費やしていることなのでしょうか?

並行性テストを実行する場合、InnoDBはに反対してもMEMORY、勝つ可能性が非常に高くなります。

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

実際、オラクルは、InnoDBの方がMyISAMを8.0から削除しているよりも優れていると確信しています。

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

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

結論:MyISAMを使用しない


2
MySQLデータベース技術は進歩しています。そして、StackOverflowの質問と回答は、過去に取り残されています。メインのMyISAMとInnoDBの間の違いは、以下のサーバーの「負荷」について、そしてより多くのサポートについて参照整合性の取引だけでなく、同時実行およびリカバリ(10)
spencer7593

12

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

MariaDB

http://mariadb.org/

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

Perconaサーバー

https://launchpad.net/percona-server

MySQLの強化されたドロップイン置換、パフォーマンスの向上、診断の改善、機能の追加。


1
私はそれらの両方を使用しています(Perconaをプロダクションで、MariaをWindows開発で)。彼らはより速くなり、完全に機能します。
Moshe L

4
これは質問の答えにはなりません。MariaDBとPerconaはMySQLの分岐であり、InnoDBエンジンとMyISAMエンジンも使用します。
dr_

12

注意してください、私はOracleのための真のですが、MySQLのために満たされていないものが言うそうならば、MySQLでの私の仕事は完全に個人的な、自分の時間にしてきたが、私の正式な教育と経験は、オラクルであることを、私は謝罪します。2つのシステムは多くを共有していますが、関係理論/代数は同じであり、リレーショナルデータベースは依然としてリレーショナルデータベースですが、まだ多くの違いがあります!!

InnoDBがトランザクションベースであること(および行レベルのロック)が特に好きです。つまり、Webアプリケーションの1つの「操作」に対して、更新、挿入、作成、変更、削除などを何度も行う可能性があります。発生する問題は、これらの変更/操作の一部のみがコミットされるが、他はコミットされない場合、ほとんどの場合(データベースの特定の設計に応じて)、データ/構造が競合するデータベースになることです。

注: Oracleでは、create / alter / dropステートメントは「DDL」(データ定義)ステートメントと呼ばれ、暗黙的にコミットをトリガーします。「DML」(データ操作)と呼ばれる挿入/更新/削除ステートメントは自動的にコミットされませんが、DDL、コミット、または終了/終了が実行された場合(またはセッションを「自動コミット」に設定した場合)、またはクライアントが自動コミットする場合)。Oracleで作業する場合は、そのことを認識することが不可欠ですが、MySQLが2種類のステートメントをどのように処理するかはわかりません。このため、MySQLに関してはこれがよく分からないことを明確にしたいと思います。Oracleでのみ。

トランザクションベースのエンジンが優れている例:

私またはあなたが無料のイベントに参加するためにサインアップするWebページにいるとします。システムの主な目的の1つは、最大100人までしかサインアップできないようにすることです。イベントのために。サインアップが100に達すると、少なくとも他のユーザーがキャンセルするまで、システムはそれ以上サインアップを無効にします。

この場合、ゲスト用のテーブル(名前、電話、電子メールなど)と、サインアップしたゲストの数を追跡する2番目のテーブルがある場合があります。したがって、1つの「トランザクション」に対して2つの操作があります。次に、ゲスト情報がGUESTSテーブルに追加された後、接続が失われたか、同じ影響のあるエラーが発生したとします。GUESTSテーブルが更新(挿入)されましたが、「空席」を更新する前に接続が失われました。

これでゲストテーブルにゲストが追加されましたが、利用可能な座席数は正しくありません(たとえば、値が実際には84の場合、値は85です)。

もちろん、これを処理するには多くの方法があります。たとえば、「ゲストテーブルの行数から100を引いた数」で利用可能な座席を追跡したり、情報が一貫していることを確認するコードなどです。 InnoDBのような、いずれかのエンジンALL操作のコミットは、またはされているNONEそれらのはありません。これは多くの場合に役立ちますが、私が言ったように、安全であるための唯一の方法ではありません(ただし、プログラマー/スクリプトライターではなく、データベースが適切に処理する方法)。

これがすべて「トランザクションベース」とは、このコンテキストでは、トランザクション全体が正常に成功するか、も変更されないことを除いて、このコンテキストでは本質的に意味します。部分的な変更のみを行うと、データベース、おそらくそれを破壊しています...

しかし、もう一度言います。混乱を避ける唯一の方法ではありません。しかし、これはエンジン自体が処理するメソッドの1つであり、手動で行う代わりに、「トランザクションが成功したかどうか、および失敗した場合(再試行など)」について心配するだけで、コード/スクリプトを作成できます。データベースの外部から「手動」でチェックするコードを記述し、そのようなイベントに対してさらに多くの作業を行う。

最後に、テーブルロックと行ロックについてのメモ:

免責事項: 私は、MySQLに関して、以下のことすべて、および仮想の/例の状況では間違っている可能性がありますを検討するものですが、私は何に間違っている可能性があり、正確に MySQLで原因が破損することが可能です。ただし、一般的なプログラミングでは、MySQLにそのようなことを回避するためのより多くのメカニズムがあっても、例は非常に現実的です...

とにかく、一度に許可される接続の数はロックされたテーブルでは機能しないと主張している人々に同意することには、かなりの自信があります。実際、複数の接続がテーブルをロックすることの要です!! 他のプロセス/ユーザー/アプリが同時に変更を加えることによってデータベースを破壊することができないように。

同じ行で2つ以上の接続が機能していると、どうすれば本当に悪い日になりますか?同じ行の同じ値を更新したい/必要とする2つのプロセスがあるとします。たとえば、行がバスツアーのレコードであり、2つのプロセスがそれぞれ同時に「riders」または「available_seats」を更新したいとします。 「現在の値+ 1」としてフィールド。

段階的にこれを仮定してみましょう:

  1. プロセス1が現在の値を読み取り、それが空であるとしましょう。これまでのところ「0」です。
  2. プロセス2は、現在の値も読み取りますが、これはまだ0です。
  3. 1つの書き込みを処理します(現在+ 1)。これは1です。
  4. プロセス2 2 書き込む必要がありますが、プロセス1が新しい値を書き込む前に現在の値を読み取るため、テーブルにも1を書き込みます。

アイム一定ではない 2つの接続は、そのように最初の書き込みの前に両方の読み取りを混在できること...しかし、もしそうでなければ、私はまだとの問題を参照してくださいになります。

  1. プロセス1は、現在の値である0を読み取ります。
  2. 1つの書き込みを処理します(現在+ 1)、つまり1。
  3. プロセス2は、現在の値を読み取ります。ただし、1つのDID書き込み(更新)を処理している間は、データをコミットしていません。そのため、同じプロセスだけが更新した新しい値を読み取ることができ、他のすべてのユーザーはコミットがあるまで古い値を確認できます。

また、少なくともOracleデータベースには、分離レベルがあります。言い換えれば、時間を無駄にすることはありません。これはその主題についての良い記事であり、各分離レベルには長所と短所があり、トランザクションベースのエンジンがデータベース内でどれほど重要であるかと一緒になっています...

最後に、MyISAM内には、外部キーやトランザクションベースの相互作用ではなく、さまざまな保護手段が存在する可能性があります。1つには、テーブル全体がロックされているという事実があるため、トランザクションやFKが必要になる可能性が低くなります

そして、悲しいかな、これらの同時実行の問題を認識している場合は、はい、安全性を低下させてアプリケーションを作成し、そのようなエラーが発生しないようにシステムを設定できます(データベース自体ではなく、コードが責任を負います)。ただし、私の意見では、できる限り多くの保護手段を使用し、防御的にプログラミングし、人的エラーを完全に回避することは不可能であることを常に認識していることが常に最善だと思います。それは誰にでも起こります、そして、それに対して免疫があると言う誰もが嘘をついているか、または「Hello World」アプリケーション/スクリプトを書く以上のことをしていません。;-)

そのうちのいくつかが誰かに役立つことを願っていますが、それ以上に、私は今、仮定の犯人ではなく、誤って人間になっていることを願っています!! そうだとすれば申し訳ありませんが、この特定のコンテキストで潜在的でない場合でも、例について考えたり、リスクを調査したりするのは良い例です。

お気軽に私を訂正し、この「回答」を編集して、反対票を投じてください。私の悪い仮定を別のもので修正するのではなく、改善してみてください。;-)

これが私の最初の返答です。免責事項なども含めて、長さはご容赦ください。絶対に自信がないときは、傲慢になりたくないだけです。



5

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


2
フルテキストインデックス作成はMyISAMでのみ可能で、InnoDBではできません。
Pixel Elephant

2
@PixelElephant、それはMySQL 5.6で変更され始めています。InnoDBにはフルテキストインデックスタイプがありますが、これまでのところ、IMHOを運用環境で使用する準備はできていません。
Bill Karwin 2013

1
「フルテキストインデックス作成は、InnoDBではなくMyISAMでのみ可能です」:MySQL> = 5.6以降、これ以上当てはまりません。dev.mysql.com/doc/refman/5.6/en/fulltext-search.htmlを参照してください。
Hibou57 2013

5

Myisamにはロックの競合がありますが、使用する高速ロック取得方式のため、ほとんどのシナリオでInnoDbよりも高速です。私はInnodbを何度か試しましたが、何らかの理由で常にMyIsamにフォールバックしました。また、InnoDBは巨大な書き込み負荷でCPUを非常に集中的に使用する可能性があります。


4

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

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


4

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


2
トランザクションを使用し、InnoDBエンジンの自動コミットをオフにすると、同じパフォーマンスが得られます。
stanleyxu2005 2012

IDKの場合は同じパフォーマンスですが、それは私がより複雑なアプリケーションで行うものであり、スピードアップします。
user965748 2012

1
実験の正確な詳細を提供できませんでした-どの構成設定ですか?以前のテーブルには何がありましたか?どんなデータ?そしておそらく最も重要なこと-挿入は順次でしたか?平行?彼らのタイミングは何でしたか?CPUコアはいくつありますか?スレッド?など
einpoklum

3

myisamはそのタイプのワークロード(同時実行書き込み数が多い)のNOGOです。innodbをそれほど経験していません(3回テストして、それぞれのケースでパフォーマンスが低下したことがわかりましたが、最後のテストからしばらく時間が経過しています)。 mysqlを実行する必要はありません。postgresが同時書き込みをより適切に処理するため、試してみることを検討してください。


3

要するに、多くのINSERTとUPDATE命令を処理できる信頼できるデータベースを必要とする何かに取り組んでいるなら、InnoDBは良いことです。

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

あなたはチェックアウトしたいかもしれません。
InnoDBの
長所と短所MyISAMの長所と短所


2

私はこれが人気がないことを知っていますが、ここに行きます:

myISAMは、トランザクションや参照の整合性などのデータベースの重要な要素をサポートしていないため、アプリケーションの不具合やバグが発生することがよくあります。データベースエンジンでサポートされていない場合でも、適切なデータベース設計の基礎を学ぶことはできません。

データベースの世界で参照整合性またはトランザクションを使用しないのは、ソフトウェアの世界でオブジェクト指向プログラミングを使用しないのと同じです。

InnoDBは現在存在しています。代わりにそれを使用してください!MySQLの開発者でさえ、myISAMがすべてのレガシーシステムでデフォルトであった元のエンジンであるにもかかわらず、これを新しいバージョンのデフォルトエンジンに変更することを最終的に認めました。

いいえ、読み取りまたは書き込みを行っているかどうか、またはパフォーマンスに関する考慮事項は関係ありません。myISAMを使用すると、さまざまな問題が発生する可能性があります。たとえば、次のような問題が発生します。データベースの同期を実行していて、同時に他の誰かがmyISAMに設定されたテーブルにアクセスするアプリケーションにアクセスした。トランザクションサポートの不足とこのエンジンの一般的に信頼性が低いため、データベース全体がクラッシュし、mysqlを手動で再起動する必要がありました。

過去15年間の開発で、私は多くのデータベースとエンジンを使用しました。myISAMは、この期間中に約10回、他のデータベースで1回だけクラッシュしました。ちなみに、これはMicrosoft SQLデータベースで、一部の開発者が誤ったCLRコード(共通言語ランタイム-基本的にはデータベース内で実行されるC#コード)を書き込んだのですが、データベースエンジンの責任ではありませんでした。

高品質で高可用性、高性能のアプリケーションは機能しないためmyISAMを使用すべきではなく、フラストレーションのないエクスペリエンスを実現するほど堅牢でも安定でもないという他の回答にも同意します。詳細については、Bill Karwinの回答を参照してください。

PS Gottaは、myISAMのファンが反対票を投じたときにそれを気に入っていますが、この回答のどの部分が間違っているかはわかりません。


5
私は反対票を投じませんでしたが、仮にそうしたとしても、決して使用しないようにアドバイスすることになります。開発者の語彙でこの単語を決して打ち消すべきではありません...「決して決して言わない」という警告。
Hubson bropa 2016年

1

その読み取り/書き込みの比率については、InnoDBの方がパフォーマンスが良いと思います。ダーティリードで問題ないので、(余裕がある場合)スレーブに複製して、すべてのリードをスレーブに送ることができます。また、一度に1つのレコードではなく、一括で挿入することを検討してください。


1

ほとんどの場合、新しいプロジェクトを開始するたびに、この同じ質問をググって、新しい答えが出てくるかどうかを確認します。

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

キー/値ルックアップを実行するテーブルがあります...これですべてです。ハッシュキーの値(0〜512バイト)を取得する必要があります。このDBには多くのトランザクションがありません。テーブルはときどき(全体的に)更新されますが、トランザクションはありません。

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

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

MyISAMテーブルを使用して金融トランザクションを実行することはありませんが、単純な検索の場合は、テストする必要があります。通常、クエリの数は2倍から5倍です。

それをテストし、私は議論を歓迎します。


1

70%が挿入で30%が読み取りの場合は、InnoDB側のようになります。


0

ボトムライン:データの大きなチャンクを選択してオフラインで作業している場合、MyISAMはおそらくより良い(はるかに良い)速度を提供します。

MyISAMがInnoDBよりもはるかに効率的である状況がいくつかあります。大規模なデータダンプをオフラインで操作する場合(テーブルロックのため)。

例:VARCHARフィールドをキーとして使用するNOAAからcsvファイル(15Mレコード)を変換していました。InnoDBは、利用可能なメモリの大きなチャンクがあっても、永遠にかかっていました。

これはcsvの例です(最初と3番目のフィールドはキーです)。

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,

私がする必要があるのは、観測された気象現象のバッチオフライン更新を実行することなので、データを受信するためにMyISAMテーブルを使用し、キーでJOINSを実行して、受信ファイルをクリーンアップし、VARCHARフィールドをINTキー(これは、元のVARCHAR値が格納されている外部テーブル)。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.