6

MyISAM がレコードを物理的に保存する方法と、レコードの挿入と削除後に構造を維持する方法を理解しようとしています。次のリンクを読みました。

正しく理解しているかどうかを確認したいので、正しくない場合は修正してください。

固定サイズのレコード

MyISAM 固定サイズ レコード

  • 削除マーカーは、レコードが削除されるかどうかを決定します。
  • レコード ヘッダーは、行のどの列に NULL 値が含まれているかを保持します
  • データの長さは固定です。

可変長レコード

ここに画像の説明を入力

  • 削除マーカーは BLOCK_DELETED ブロック タイプに置き換えられます
  • レコード ヘッダーには、データの長さと未使用データの長さが保持されます

ここに画像の説明を入力

  • 1 つのレコードを、オーバーフロー ポインタで接続された複数のブロックに分割できます。

消す

ここに画像の説明を入力

  • 可変サイズのレコードの場合、ブロック タイプを BLOCK_DELETED に変更します
  • 新しく削除されたレコードの前のポインタが最後に削除されたレコードを指すようにすることで、削除されたすべてのレコードの二重リンク リストを維持します。次に、最後に削除されたレコードの次のポインターは、新しく削除されたレコードを指します。
  • 固定サイズのレコードの場合は、削除マーカーを削除済みに変更するだけです。(二重リンクリストを使用して、削除されたすべてのレコードを固定サイズのレコードに接続するかどうかは不明です)

挿入

  • 未使用スペース(削除されたレコード)がない場合は、ファイルの最後にデータを追加します
  • 新しく挿入されたレコードに適合する未使用スペースがある場合は、そこに新しいレコードを書き込みます。
  • 新しく挿入されたレコードよりもはるかに大きな未使用スペースがある場合は、新しいレコードと削除されたレコードの 2 つのレコードに分割します。
  • 新しく挿入されたレコードよりも小さい未使用スペースがある場合は、そこにデータを書き込み、オーバーフロー ポインターを別のブロックの未適合データを指すようにします。

更新中

  • ユーザーが既存のデータをより長いデータで更新するとどうなりますか? MyISAM はレコードを削除済みとしてマークし、新しいデータに適合する場所を見つけますか、それとも単にオーバーフロー ポインターを使用して適合しないデータを指すのでしょうか?

もう一度質問を要約する

正しく理解しているかどうかを確認したいので、正しくない場合は修正してください。

追加の質問

  • レコード構造がオーバーフロー ポインターと未使用の領域でいっぱいになる可能性があるため、テーブルが何度も削除および挿入された場合、非常に非効率的でしょうか?
4

1 に答える 1

5

MyISAM に関する質問の情報は的を射ています。ただし、追加の 2 つの質問にお答えしたいと思います。

最新の質問

ユーザーが既存のデータをより長いデータで更新するとどうなりますか? MyISAM はレコードを削除済みとしてマークし、新しいデータに適合する場所を見つけますか、それとも単にオーバーフロー ポインターを使用して適合しないデータを指すのでしょうか?

によると

sdkm

第10章:「ストレージエンジン」ページ196 パラグラフ7は言う

可変長のレコードの場合、形式はより複雑になります。最初のバイトには、レコードのサブタイプを説明する特別なコードが含まれています。後続のバイトの意味は各サブタイプによって異なりますが、共通のテーマは、レコードの長さ、ブロック内の未使用のバイト数、NULL 値インジケータ フラグ、および場合によってはポインタを含む一連のバイトがあることです。レコードが以前に作成されたスペースに収まらず、分割する必要があった場合のレコードの継続。これは、1 つのレコードが削除され、その場所に挿入される新しいレコードが元のレコードのサイズを超える場合に発生する可能性があります。storage/myisam/mi_dynrec.c の switch ステートメント in_mi_get_block_info() を調べると、さまざまなコードの意味の詳細を取得できます。

その段落に基づいて、挿入する新しいデータが以前に割り当てられたブロックに収まらない場合にのみ、古いレコードがリンケージ データで上書きされます。これにより、多くの肥大化した行が発生する可能性があります。

追加の質問

レコード構造がオーバーフロー ポインターと未使用の領域でいっぱいになる可能性があるため、テーブルが何度も削除および挿入された場合、非常に非効率的でしょうか?

私の以前の回答から、持っているブロックがたくさんあるでしょう

  • スペースのブロック
  • レコードの長さ
  • ブロック内の未使用バイト数
  • NULL 値インジケータ フラグ
  • レコードが以前に作成されたスペースに収まらず、分割する必要があった場合、レコードの継続へのポインターである可能性があります

このようなレコード リンクは、サイズの大きいデータが挿入されているすべての行の先頭から開始されます。これにより、MyISAM テーブル.MYDファイルがすぐに肥大化する可能性があります。

提案

MyISAM のデフォルトの行形式は動的です。テーブルが動的で、多くの INSERT、UPDATE、および DELETE が発生する場合、そのようなテーブルは最適化する必要があります。

OPTIMIZE TABLE mytable;

別の方法があります。テーブルの行形式を Fixed に切り替えます。そうすれば、すべての行が同じサイズになります。行フォーマットを固定にする方法は次のとおりです。

ALTER TABLE mytable ROW_FORMAT=Fixed;

固定行形式でも、使用可能なレコードを見つけるのに時間がかかる必要がありますが、その時間は O(1) の検索時間になります (平たく言うと、行数に関係なく、使用可能なレコードを見つけるのにかかる時間は同じです)テーブルにある、または削除された行の数)。次のように、 concurrent_insertを有効にすることで、その手順をバイパスできます。

これを my.cnf に追加します

[mysqld]
concurrent_insert = 2

MySQL の再起動は不要です。とにかく走れ

mysql> SET GLOBAL concurrent_insert = 2;

これにより、空き領域を探すことなく、すべての INSERT がテーブルの後ろに移動します。

固定行テーブルの利点

  • INSERT、UPDATE、および DELETE は多少高速になります。
  • SELECT は 20 ~ 25% 高速です

これは、固定されている行フォーマットに対して SELECT が高速化されているという私の投稿の一部です。

固定行テーブルの欠点

ほとんどの場合、 を実行するALTER TABLE mytable ROW_FORMAT=Fixed;と、テーブルが 80 ~ 100% 拡大する可能性があります。ファイル (MyISAM テーブルの.MYIインデックス ページ) も同じ割合で大きくなります。

エピローグ

MyISAM テーブルの速度が必要で、より大きなテーブルを使用できる場合は、別の提案が必要になります。各 MyISAM テーブルのスペースを節約したい場合は、行形式をそのまま (動的) にします。OPTIMIZE TABLE mytable;動的テーブルでは、より頻繁にテーブルを圧縮する必要があります。

于 2013-05-29T20:08:09.553 に答える