sql >> データベース >  >> RDS >> Mysql

MySQLvarcharインデックスの長さ

    2021年9月編集:MySQL 8.0を数年使用しているので、ここにいくつかの更新情報があります。

    MySQLマニュアルには、非常に有益なページ utf8mb3間の変換について (現在はutf8とも呼ばれます )およびutf8mb4utf8mb3 は非推奨であり、削除されます 最終的;削除されると、現在のエイリアスutf8utf8mb4を参照します 代わりに。

    非推奨のutf8mb3を使用 、utf8mb4を使用すると、インデックスに最大255文字を格納できます。 、最大191、COMPACTを使用する場合 またはREDUNDANT 行形式。

    COMPRESSEDを使用 またはDYNAMIC 行形式、インデックスキープレフィックスは最大3072バイトです。これらを使用すると、utf8mb3に対して最大1024文字のインデックスを作成できます。 、およびutf8mb4の場合は768文字 。

    以下は私の以前の回答で、文字の数の背後にあるロジックの一部を説明しています。 バイト数に対してインデックスを付けることができます 。

    私は自分の研究のために答えを修正しなければなりません。私はもともとこれを投稿しました(自分自身を引用):

    答えは、文字が何バイトになるかわからないため、インデックスに含まれる文字数がわからないということだと思います(マルチバイト文字を除外するために何かをしない限り)。

    よくわかりませんが、それでも正しいかもしれませんが、私が考えていた方法ではありません。

    正解は次のとおりです。

    MySQLは、utf8文字ごとに3バイトを想定しています。 256x3 =768であり、767バイトの制限を超えるため、255文字が列ごとに指定できる最大インデックスサイズです。

    インデックスサイズを指定しない場合、MySQLは最大サイズ(つまり、列あたり255)を選択します。一意のインデックスにはセル値全体が含まれている必要があるため、長さが255を超えるutf8列にUNIQUE制約を設定することはできません。ただし、通常のインデックスを使用できます。最初の255文字(または最初の767バイト?)にインデックスを付けるだけです。そして、それは私にとってまだいくつかの謎があるところです。

    ミステリー:安全のために、MySQLが1文字あたり3バイトを想定している理由がわかります。そうしないと、UNIQUE制約が破られる可能性があるためです。しかし、ドキュメントは、インデックスが実際には文字ではなくバイト単位でサイズ設定されていることを示唆しているようです。したがって、25 5を配置するとします。 varchar(25 6 のchar(765バイト)インデックス ) 桁。保存する文字がすべてASCIIの1バイト文字(A-Z、a-z、0-9など)の場合は、列全体を767バイトのインデックスに収めることができます。そして、それが実際に起こることのようです。

    以下は、文字、バイトなどに関する私の元の回答からのいくつかの詳細情報です。

    wikipedia によると 、UTF-8文字の長さは1、2、3、または4バイトです。ただし、このmysqlドキュメント 、最大文字サイズは3バイトであるため、255文字を超える列インデックスインデックスはそのバイト制限に達する可能性があります。しかし、私が理解しているように、そうではないかもしれません。ほとんどの文字がASCII範囲にある場合、平均文字サイズは1バイトに近くなります。たとえば、平均文字サイズが1.3バイト(ほとんどは1バイトですが、かなりの数の2〜3バイト文字)の場合、767/1.3のインデックスを指定できます

    したがって、ほとんどが1バイトの文字を格納している場合、実際の文字数の制限は次のようになります:767 / 1.3 =590。しかし、それは機能する方法ではないことがわかります。 255文字が制限です。

    このMySQLドキュメント で説明されているように 、

    プレフィックス制限はバイト単位で測定されますが、CREATE INDEXステートメントのプレフィックス長は、非バイナリデータ型(CHAR、VARCHAR、TEXT)の文字数として解釈されます。マルチバイト文字セットを使用する列のプレフィックス長を指定する場合は、これを考慮してください。

    MySQLは、varchar列のキーサイズを決定するために、私が行ったように計算/推測を行うように人々にアドバイスしているようです。しかし実際にはできません utf8列に255より大きいインデックスを指定します。

    最後に、もう一度私の2番目のリンクを参照すると、これもあります:

    innodb_large_prefix構成オプションが有効になっている場合、DYNAMICおよびCOMPRESSED行フォーマットを使用するInnoDBテーブルの場合、この長さの制限は3072バイトに引き上げられます。

    したがって、必要に応じて、少し調整することで、はるかに大きなインデックスを取得できるようです。行の形式が動的または圧縮されていることを確認してください。その場合、おそらく1023文字または1024文字のインデックスを指定できます。

    ちなみに、[utf8mb4文字セット][4]を使用して4バイト文字を格納できることがわかりました。utf8文字セットは明らかに["plane0"文字][5]のみを格納します。

    編集:

    tinyint(1)列を持つvarchar(511)列に複合インデックスを作成しようとしたところ、最大インデックスサイズが767バイトであるというエラーメッセージが表示されました。これにより、MySQLはutf8文字セット列に1文字あたり3バイト(最大)が含まれると想定し、最大255文字を使用できると思います。しかし、おそらくそれは複合インデックスの場合のみです。詳細がわかり次第、回答を更新します。しかし、今のところ、これは編集として残しておきます。



    1. SQL-サーバーのIPアドレスを取得するためのクエリ

    2. MariaDBでのTRIM_ORACLE()のしくみ

    3. インデックスを適切に使用していないOracleバインド変数の問題

    4. パラメーター化されたクエリは、提供されなかったパラメーターを予期します