web-dev-qa-db-ja.com

MySQLでMEMORYストレージエンジンを使用しない**理由**は何ですか?

私は最近、MySQLに知らない「メモリ」エンジンがあることを発見しました(私のデータベース作業のほとんどは趣味のプロジェクトのためのものなので、自分が必要とするものを学びます)。このオプションを使用するとパフォーマンスが大幅に向上するようですので、それに伴う欠点があるのではないかと思います。私が知っている2つは次のとおりです。

  1. 問題のテーブルを保持するのに十分なRAM=が必要です。
  2. マシンがシャットダウンすると、テーブルは失われます。

AWS EC2を使用しており、必要に応じてより多くのメモリを持つインスタンスタイプに移動できるので、#1は問題にならないはずです。必要に応じてディスクにダンプを戻すことで、#2を軽減できると思います。

他にどんな問題がありますか?メモリエンジンは、MyISAMやInnoDBのどちらよりもパフォーマンスを低下させる可能性がありますか?このエンジンではインデックスが異なるものを読んだと思います。これは私が心配する必要があるものですか?

30
Michael McGowan

http://dev.mysql.com/doc/refman/5.1/en/memory-storage-engine.html で機能の可用性リストを見ると、考えられる2つの問題が飛び出します。

  1. トランザクションまたはFKのサポートがないため、独自のコードでトランザクションの整合性と参照の整合性を管理する必要がありました(これは、DBにこれを実行させるよりもはるかに効率が悪い可能性がありますが、それはアプリのアプリケーションに大きく依存します)予想される行動パターン)。
  2. テーブルレベルのロックのみ:アプリが同じテーブルセットへの複数の同時ライターを必要とする場合、または読み取り操作がロックを使用して一貫性のあるデータを読み取ることを保証する場合、これはスケーラビリティの大きな障壁になる可能性があります。より細かいロックの細分性をサポートすると、十分なコンテンツが現在RAMにキャッシュされている場合、パフォーマンスが大幅に向上します。

それ以外に、十分なRAMがあると仮定すると、メモリベースのテーブルはディスクベースのテーブルよりも高速になります。明らかに、サーバーインスタンスがリセットされたときに何が起こるかという問題に対処するために、スナップショットをディスクに取り込むことを考慮する必要があります。これは、データを頻繁にキャプチャする必要がある場合、全体的なパフォーマンスの利点を完全に無効にする可能性があります(このようなインスタンスのデータは、1日に1回だけバックアップを取ることができますが、ほとんどの場合それは受け入れられません)。

代替策は次のとおりです。

  1. ディスクベースのテーブルを使用しますが、すべてのRAMでそれらをすべて保持するのに十分以上のRAMがあることを確認してください(そして "十分なRAM"はマシン上の他のプロセスを説明する必要があるため、OS IO buffers/cacheなど)
  2. 各起動時にテーブルのコンテンツ全体(すべてのデータとインデックスページ)をスキャンして、各テーブルのSELECT * FROM <table> ORDER BY <pkey fields>に続いて各インデックスのSELECT <indexed fields> FROM <table> ORDER BY <index fields>を使用してコンテンツをメモリにプリロードします。

このようにして、すべてのデータがRAMに格納され、書き込み操作のI/Oパフォーマンスについてのみ心配する必要があります。アプリの共通のワーキングセットがDB全体よりもはるかに小さい場合(通常、ほとんどのアプリケーションでは、ほとんどのユーザーは最も最近のデータのみを表示します)、どれだけ選択するかを選ぶ方がよいでしょう。スキャンしてメモリにプリロードし、残りをオンデマンドでディスクからロードできるようにします。

27
David Spillett

メモリストレージエンジンを使用しないケースはたくさんありますが、InnoDBの方が高速になる場合があります。単純なシングルスレッドテストではなく、同時実行性について考える必要があるだけです。

十分な大きさのバッファープールがある場合、InnoDBも読み取り操作のために完全にメモリ常駐になります。データベースにはキャッシュがあります。彼らは自分自身を温めます!

また、行レベルのロックと [〜#〜] mvcc [〜#〜] の値を過小評価しないでください(リーダーはライターをブロックしません)。書き込みをディスクに保持する必要がある場合は、「遅くなる」ことがあります。しかし、少なくとも、書き込み操作中は、メモリテーブル(MVCCではなく、テーブルレベルのロック)のようにブロックすることはありません。

15
Morgan Tocker

記録のために。いくつかの情報を格納するために、Mysqlテーブルをメモリでテストしました。そして、同じ情報を格納するためにPHPのAPC(APCu)をテストしました。

58000レジストリの場合。 (varchar + integer + date)。

  1. テキスト形式(csv形式)の24mbオリジナル情報。
  2. PHPのAPCは44.7MBのRAMを使用します。
  3. Mysqlのテーブルは575MBのRAMを使用します。

テーブルには単一のインデックスしかないので、それが主な要因であるとは思いません。

結論:

メモリテーブルは「大きな」テーブルのオプションではありませんはメモリを使いすぎているためです。

3
magallanes

MEMORYベースのテーブルのもう1つの欠点は、同じクエリで複数回参照できないことです。少なくともその動作はv5.4まで見られました。 CTE(v8.x以降)では、複雑な手順でmemベースの中間テーブルを使用する必要はありません。

2
Kondybas

以前の回答に加えて。 MySQL 5.7マニュアルから直接:

「MEMORYのパフォーマンスは、更新処理時のシングルスレッド実行とテーブルロックのオーバーヘッドによる競合によって制約されます。これにより、特に書き込みを含むステートメントミックスの場合、負荷が増加したときのスケーラビリティが制限されます。」

...そしてこれは非常に現実的な制限です。たとえば、複数のセッションでニースの高速MEMORY一時テーブルを作成しようとすると、シングルスレッドがパフォーマンスのボトルネックを引き起こす可能性があります。

1
Eljuan

MEMORYテーブルは、特にデータの大規模なサブセットや、保持が重要なものの永続的なストレージを対象としたものではありません。私の経験からの最高の目的は、複雑な手順での一時テーブルの作成中および作成中に一時的なレコードを格納することです。これは、エンジンのキーバッファーしきい値が十分に高く設定されていれば、この目的のための他のほとんどのテーブルタイプよりも大幅に高速に実行されます。ディスク書き込み。ディスクI/Oがないため、これはMyISAMまたはInnoDBよりも桁違いに高速に動作でき、特定のプロシージャ内にカプセル化されているテーブルの場合、インデックス作成と関係はそれほど重要ではありません。永続性が期待される場所です。

1
mopsyd

MySQLおよびMariaDBのマニュアルによると、BLOBおよびCLOB(さまざまなTEXTタイプ)はMEMORYストレージではサポートされていません。私たち自身の目的では、これによりMEMORYストレージエンジンはほとんど役に立たなくなりました。

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

MEMORYテーブルにBLOBまたはTEXT列を含めることはできません。

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

VARCHARなどの可変長型は、MEMORYテーブルで使用できます。 BLOB列またはTEXT列はMEMORYテーブルではサポートされていません。

データベースの一部のみをMEMORYストレージに変換しようとすると、ストレージエンジン間外部キーがサポートされていないことがわかりました。したがって、BLOB/CLOBを含む、テーブルへの外部キー参照が必要なすべてのテーブルも、非メモリストレージタイプである必要があります(少なくとも、これはInnoDB子テーブルに影響します)。

1
user2134886