非公式MySQL 8.0オプティマイザガイド

View the Project on GitHub

  1. はじめに
  2. サーバーアーキテクチャー
  3. B+ツリー インデックス
  4. Explain
  5. オプティマイザ トレース
  6. 論理変換
  7. コストベース最適化
  8. ヒント
  9. プランの比較
  10. 複合インデックス
  11. カバリングインデックス
  12. Visual Explain
  13. 変わりゆく実行計画(Transient Plans)
  14. サブクエリー
  15. 共通テーブル式(CTE)とビュー
  16. 結合
  17. 集約
  18. ソート
  19. パーティショニング
  20. クエリーリライト
  21. 不可視インデックス
  22. クエリープロファイリング
  23. JSONと生成列
  24. 文字セット

文字セット

原文URL: http://www.unofficialmysqlguide.com/character-sets.html
翻訳者: taka-h (@takaidohigasi)

MySQL 8.0では最新のUnicode 9.0がutf8mb4という名前でサポートされています。utf8mb4はそれぞれの文字が1から4バイトの可変長です。 可変長の文字数とバイト数が少し異なるケースはたくさんあり例えば次のようなケースがあげられます。

  1. 列をVARCHAR(n)で作成した時、nは文字列長を表します。データの保存に必要なバイト数は(多くの場合はこれより小さいのですが)最大この4倍となりえます。
  2. 内部的にはInnoDBストレージエンジンは常に1utf8mb4VARCHARCHARTEXTデータ型の(インデックス内およびテーブルの行にて)可変長として保存しています。
  3. マテリアライズの一部として利用されるメモリ内の一時テーブルは固定長です。utf8mb4文字セットを利用している場合は一時テーブルがより大きくなったり、より早くディスクにあふれたりすることになる場合があります。
  4. データをソートするために利用されているバッファーは可変長です(MySQL 5.7より)。
  5. EXPLAINは常にインデックスの可変長(バイト長)の最大長を示します。もっと少ない領域しか必要とならない場合がしばしば発生します。

例37は、latin1文字セットでCHAR(52)の列へのインデックスを利用していることを伝えているEXPLAINとなります。テーブルをutf8mb4に変換した後、必要な保存容量は増えませんが、EXPLAINではkey_lengthが増えていることが確認できます。

例37: EXPLAINがインデックスの最大キー長を示す(latin1文字セットにて)

     EXPLAIN FORMAT=JSON
     SELECT * FROM Country WHERE name='Canada';
     {
       "query_block": {
         "select_id": 1,
         "cost_info": {
           "query_cost": "1.20"
         },
         "table": {
           "table_name": "Country",
           "access_type": "ref",
           "possible_keys": [
             "Name"
           ],
           "key": "Name",
           "used_key_parts": [
             "Name"
           ],
           "key_length": "52",  # CHAR(52)
           "ref": [
             "const"
           ],
           "rows_examined_per_scan": 1,
           "rows_produced_per_join": 1,
           "filtered": "100.00",
           "cost_info": {
             "read_cost": "1.00",
             "eval_cost": "0.20",
             "prefix_cost": "1.20",
             "data_read_per_join": "264"
           },
           "used_columns": [
             "Code",
             "Name",
             "Continent",
             "Region",
             "SurfaceArea",
             "IndepYear",
             "Population",
             "LifeExpectancy",
             "GNP",
             "GNPOld",
             "LocalName",
             "GovernmentForm",
             "HeadOfState",
             "Capital",
             "Code2"
           ]
         }
       }
     }

例38: EXPLAINがインデックスの最大キー長を示す(utfmb4文字セットにて)

     ALTER TABLE Country CONVERT TO CHARACTER SET utf8mb4;
     EXPLAIN FORMAT=JSON
     SELECT * FROM Country WHERE name='Canada';
     {
       "query_block": {
         "select_id": 1,
         "cost_info": {
           "query_cost": "1.20"
         },
         "table": {
           "table_name": "Country",
           "access_type": "ref",
           "possible_keys": [
             "Name"
           ],
           "key": "Name",
           "used_key_parts": [
             "Name"
           ],
           "key_length": "208", # CHAR(52) * 4 = 208
           "ref": [
             "const"
           ],
           "rows_examined_per_scan": 1,
           "rows_produced_per_join": 1,
           "filtered": "100.00",
           "cost_info": {
             "read_cost": "1.00",
             "eval_cost": "0.20",
             "prefix_cost": "1.20",
             "data_read_per_join": "968"
           },
           "used_columns": [
             "Code",
             "Name",
             "Continent",
             "Region",
             "SurfaceArea",
             "IndepYear",
             "Population",
             "LifeExpectancy",
             "GNP",
             "GNPOld",
             "LocalName",
             "GovernmentForm",
             "HeadOfState",
             "Capital",
             "Code2"
           ]
         }
       }
     }
  1. 行形式にDYNAMICCOMPACTおよびCOMPRESSEDを利用しているときは常に。通常は、以前のREDUNDANT行形式は実用的な利用例がありません。