EXPLAIN ( 2 )

August 11, 2018

JSON 形式の EXPLAIN

MySQL 5.6 からは JSON 形式で EXPLAIN が出力できるようになった。JSON 形式で EXPLAIN を出力するには FORMAT=JSON を指定すれば良い。

mysql> EXPLAIN FORMAT=JSON SELECT City.Name, Country.Code, CountryLanguage.Language FROM City JOIN Country ON City.CountryCode = Country.Code AND City.Id = Country.Capital JOIN CountryLanguage ON CountryLanguage.CountryCode = City.CountryCode \G;  
*************************** 1. row ***************************  
EXPLAIN: {  
  "query_block": {  
    "select_id": 1,  
    "cost_info": {  
      "query_cost": "364.15"  
    },  
    "nested_loop": [  
      {  
        "table": {  
          "table_name": "Country",  
          "access_type": "ALL",  
          "possible_keys": [  
            "PRIMARY"  
          ],  
          "rows_examined_per_scan": 239,  
          "rows_produced_per_join": 239,  
          "filtered": "100.00",  
          "cost_info": {  
            "read_cost": "7.00",  
            "eval_cost": "47.80",  
            "prefix_cost": "54.80",  
            "data_read_per_join": "169K"  
          },  
          "used_columns": [  
            "Code",  
            "Capital"  
          ],  
          "attached_condition": "(`world`.`Country`.`Capital` is not null)"  
        }  
      },  
      {  
        "table": {  
          "table_name": "City",  
          "access_type": "eq_ref",  
          "possible_keys": [  
            "PRIMARY",  
            "CountryCode"  
          ],  
          "key": "PRIMARY",  
          "used_key_parts": [  
            "ID"  
          ],  
          "key_length": "4",  
          "ref": [  
            "world.Country.Capital"  
          ],  
          "rows_examined_per_scan": 1,  
          "rows_produced_per_join": 11,  
          "filtered": "5.00",  
          "cost_info": {  
            "read_cost": "239.00",  
            "eval_cost": "2.39",  
            "prefix_cost": "341.60",  
            "data_read_per_join": "2K"  
          },  
          "used_columns": [  
            "ID",  
            "Name",  
            "CountryCode"  
          ],  
          "attached_condition": "(`world`.`City`.`CountryCode` = `world`.`Country`.`Code`)"  
        }  
      },  
      {  
        "table": {  
          "table_name": "CountryLanguage",  
          "access_type": "ref",  
          "possible_keys": [  
            "PRIMARY",  
            "CountryCode"  
          ],  
          "key": "CountryCode",  
          "used_key_parts": [  
            "CountryCode"  
          ],  
          "key_length": "9",  
          "ref": [  
            "world.Country.Code"  
          ],  
          "rows_examined_per_scan": 4,  
          "rows_produced_per_join": 50,  
          "filtered": "100.00",  
          "using_index": true,  
          "cost_info": {  
            "read_cost": "12.46",  
            "eval_cost": "10.09",  
            "prefix_cost": "364.15",  
            "data_read_per_join": "5K"  
          },  
          "used_columns": [  
            "CountryCode",  
            "Language"  
          ]  
        }  
      }  
    ]  
  }  
}  
1 row in set, 1 warning (0.00 sec)  

JSON 形式の EXPLAIN は表形式よりも表示される情報が多い。特に MySQL 5.7 からはコストに関する情報が得られるようになった。例えば上記の例だと Nested Loop により JOIN が実行され、そのコストは 364.15 であるとオプティマイザに判断されていることが分かる。
なお、JSON 形式では Extra フィールドがない。その代わりに attached_condition として具体的にどのような条件が適用されるかも分かるようになっている。

ビジュアル EXPLAIN

MySQL Workbench は、ER 図によって DB 設計を行える GUI ツールであり、その機能としてビジュアル EXPLAIN が提供されている。
こちらからダウンロードが可能。

f:id:shiro_kochi:2018××××××××:plain:w100:left

実行中のクエリに対する EXPLAIN

SHOW PROCESSLIST を用いて長時間実行している SQL がないかを調べる際に、もし長時間実行されている SQL が見つかると、なぜ時間がかかっているかを調べるために EXPLAIN コマンドを用いる。
EXPLAIN を実行するには、SHOW FULL PROCESSLIT を利用して SQL の全文を取得し、コピー/ペーストで EXPLAIN をする操作が行われることもある。しかし、実行中のクエリが膨大であったり、SQL 文が長かったりすると、この操作は面倒になる。
MySQL 5.7 では実行中の SQL に対する EXPLAIN をそのコネクション ID を指定するだけで見られるようになった。例えば長時間かかっている SQL を実行しているセッションのコネクション ID が 777 であった場合、そのコネクションに対する EXPLAIN を表示するには以下のようにする。

mysql> EXPALIN FOR CONNECTION 777  

 © 2023, Dealing with Ambiguity