web-dev-qa-db-ja.com

BLOBとTEXTがInnoDBにインラインで格納されるのはどのような場合ですか?

私はこれをググってみましたが見つかりません、あなたは見ることができます Rick James ここでそれを言及してください。

... BLOBTEXTは常に別々に保存されるわけではありません

MySQL VARCHARとTEXTデータ型の違いは何ですか? の答えは、

InnoDBはVARCHARに似ていますが、レコードの外側に完全なTEXTフィールドを格納します。

このスタンスで大々的に賛成する回答はそれだけではありません。 StackOverflowから754票で非常に明確に答えを見つけることができます。

TEXTおよびBLOBはテーブルから格納され、テーブルには実際のストレージの場所へのポインターのみが含まれます。

VARCHARはテーブルにインラインで格納されます。サイズが妥当な場合はVARCHARの方が高速ですが、トレードオフはデータとハードウェアによって異なります。実際のシナリオをデータでベンチマークする必要があります。

ここのコメントは、メーリングリストの投稿にリンクしています

MyISAMはTEXTBLOBを「インライン」に配置します。テーブルを検索している場合(範囲スキャン/テーブルスキャン)、「それらの牛の水田をまたぐ」-ディスクI/Oにはコストがかかります。つまり、この場合、インラインblobが存在するとパフォーマンスが低下します。

InnoDBはTEXTまたはBLOBの767バイトのみをインラインに配置し、残りは他のブロックに入ります。これは妥協案であり、パフォーマンスを低下させることもあります。

テキストとblobが制限内にある場合にインラインで保存することについて説明している他の投稿を見たことがありますか?制限は何ですか? InnoDBはいつBLOBとテキストを並べて格納しますか?

5
Evan Carroll

InnoDBの場合、ルールは次のようになります。

  • レコードはフラグメント化できません。
  • 少なくとも2つのレコードが1ページに収まる必要があります。
  • レコードサイズが〜7k未満の場合、すべてのフィールド値がページはめ込みに格納されます。
  • レコードサイズが〜7kより大きい場合、最初の768(COMPACT形式)または20バイト(DYNAMIC形式)がページ内に格納されます。残りの部分はページ外に保存されます。

それを確認する方法。

CREATE TABLE `t1` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` text,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1


mysql> insert into t1(name) select repeat('a', 10);
Query OK, 1 row affected (0.02 sec)
Records: 1  Duplicates: 0  Warnings: 0

mysql> insert into t1(name) select repeat('a', 8000);
Query OK, 1 row affected (0.00 sec)
Records: 1  Duplicates: 0  Warnings: 0

次に、t1.ibdstream_parser を使用します。

stream_parser -f t1.ibd

PRIMARYインデックスページのコンテンツを確認します。

# hexdump -C pages-t1.ibd/FIL_PAGE_INDEX/0000000000000046.page
00000000  97 e5 5e 36 00 00 00 03  ff ff ff ff ff ff ff ff  |..^6............|
00000010  00 00 00 00 00 27 b9 44  45 bf 00 00 00 00 00 00  |.....'.DE.......|
00000020  00 00 00 00 00 18 00 02  1f f3 80 04 00 00 00 00  |................|
00000030  00 a2 00 02 00 01 00 02  00 00 00 00 00 00 00 00  |................|
00000040  00 00 00 00 00 00 00 00  00 2e 00 00 00 18 00 00  |................|
00000050  00 02 00 f2 00 00 00 18  00 00 00 02 00 32 01 00  |.............2..|
00000060  02 00 1c 69 6e 66 69 6d  75 6d 00 03 00 0b 00 00  |...infimum......|
00000070  73 75 70 72 65 6d 75 6d  0a 00 00 00 10 00 23 80  |supremum......#.|
00000080  00 00 01 00 00 00 00 05  10 ae 00 00 01 22 01 10  |............."..|
00000090  61 61 61 61 61 61 61 61  61 61 40 9f 00 00 00 18  |aaaaaaaaaa@.....| <- this is the first record
000000a0  ff ce 80 00 00 02 00 00  00 00 05 11 af 00 00 01  |................|
000000b0  23 01 10 61 61 61 61 61  61 61 61 61 61 61 61 61  |#..aaaaaaaaaaaaa| <- this is the beginning of the second record
000000c0  61 61 61 61 61 61 61 61  61 61 61 61 61 61 61 61  |aaaaaaaaaaaaaaaa|
* <- The star means identical strings are omitted, -v will show full output.
00001ff0  61 61 61 00 00 00 00 00  00 00 00 00 00 00 00 00  |aaa.............|
00002000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00003ff0  00 00 00 00 00 70 00 63  97 e5 5e 36 00 27 b9 44  |.....p.c..^6.'.D|
00004000  97 e5 5e 36 00 00 00 03  ff ff ff ff ff ff ff ff  |..^6............|
00004010  00 00 00 00 00 27 b9 44  45 bf 00 00 00 00 00 00  |.....'.DE.......|
00004020  00 00 00 00 00 18 00 02  1f f3 80 04 00 00 00 00  |................|
00004030  00 a2 00 02 00 01 00 02  00 00 00 00 00 00 00 00  |................|
00004040  00 00 00 00 00 00 00 00  00 2e 00 00 00 18 00 00  |................|
00004050  00 02 00 f2 00 00 00 18  00 00 00 02 00 32 01 00  |.............2..|
00004060  02 00 1c 69 6e 66 69 6d  75 6d 00 03 00 0b 00 00  |...infimum......|
00004070  73 75 70 72 65 6d 75 6d  0a 00 00 00 10 00 23 80  |supremum......#.|
00004080  00 00 01 00 00 00 00 05  10 ae 00 00 01 22 01 10  |............."..|
00004090  61 61 61 61 61 61 61 61  61 61 40 9f 00 00 00 18  |aaaaaaaaaa@.....|
000040a0  ff ce 80 00 00 02 00 00  00 00 05 11 af 00 00 01  |................|
000040b0  23 01 10 61 61 61 61 61  61 61 61 61 61 61 61 61  |#..aaaaaaaaaaaaa|
000040c0  61 61 61 61 61 61 61 61  61 61 61 61 61 61 61 61  |aaaaaaaaaaaaaaaa|
*
00005ff0  61 61 61 00 00 00 00 00  00 00 00 00 00 00 00 00  |aaa.............|
00006000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00007ff0  00 00 00 00 00 70 00 63  97 e5 5e 36 00 27 b9 44  |.....p.c..^6.'.D|
00008000

これはCOMPACT形式用です。 DYNAMICCOMPRESSEDを除く)の場合も手順は同じです。

5
akuzminsky

4つの「行フォーマット」があることに注意してください。その間の主な違いは、幅の広い列の処理方法に関係しています。

参照は、DYNAMICCOMPRESSEDが「InnoDBプラグイン」に導入される数か月前の2010年の初めに書かれた回答を指します。

つまり、他のQ&Aは古くなっていると私は主張します!つまり、754票は有効ではなくなりました。

ここにいくつかの「現在の」マニュアル参照があります:

(強調鉱山)

https://dev.mysql.com/doc/refman/5.6/en/innodb-row-format-overview.html から:

BLOB およびVARCHARなどの列が長すぎてBツリーページに収まらない場合、オーバーフローページと呼ばれる個別に割り当てられたディスクページに格納されます。

https://dev.mysql.com/doc/refman/5.6/en/innodb-row-format-dynamic.html から:

ROW_FORMAT = DYNAMICまたはROW_FORMAT = COMPRESSEDを使用してテーブルが作成されると、InnoDBは長い可変長列値(VARCHAR、VARBINARY、BLOBおよびTEXTタイプの場合)を格納できます完全にオフページ、オーバーフローページへの20バイトのポインターのみを含むクラスター化インデックスレコード。

[DYNAMIC and COMPRESSED]行が長すぎる場合、クラスター化されたインデックスレコードがBツリーページに収まるまで、InnoDBはページ外ストレージとして最も長い列を選択します。 40バイト以下のTEXTおよびBLOB列は常にインラインで格納されます

[〜#〜] dynamic [〜#〜]形式は、長いデータ値の一部がページ外に格納される場合、通常すべてのデータを格納するのが最も効率的であるという考えに基づいていますオフページの値。 DYNAMIC形式では、短い列はBツリーノードに残る可能性が高いで、特定の行に必要なオーバーフローページの数を最小限に抑えます。

[〜#〜] compressed [〜#〜]行フォーマットは、動的な行フォーマットと同様のオフページストレージの内部詳細を使用します

から https://dev.mysql.com/doc/refman/5.6/en/innodb-physical-record.html (大きなCHARでもTEXT):

InnoDB [すべてのフォーマット?]は、長さが768バイト以上の固定長フィールドを可変長フィールドとしてエンコードし、オフページに格納できます。たとえば、utf8mb4の場合のように、文字セットの最大バイト長が3より大きい場合、CHAR(255)列は768バイトを超える可能性があります。

ROW_FORMAT = DYNAMICおよびROW_FORMAT = COMPRESSEDは、ROW_FORMAT = COMPACTと同じ方法でCHARストレージを処理します。

(リンクは5.6用ですが、テキストは少なくとも新しいバージョンに適用されると思います。)

VARCHAR(...)*TEXTの扱いが異なります。

7
Rick James