Hatena::ブログ(Diary)

rkajiyamaの日記 このページをアンテナに追加

2016-06-17

MySQL 5.7のGeoHash

| MySQL 5.7のGeoHashを含むブックマーク

MySQL 5.7で追加された機能一つにBoost.Geometryとの統合によるGISの強化があります。さらにGeoHashという機能が追加されています。GeoHashは地点の情報をハッシュ値として格納する機能で、ハッシュ長によって精度を変えることができます。緯度経度の値から長さの異なるGeoHashを生成し、そこから再度緯度経度の値を算出してみます。今回の例では直線距離で約3km離れた2地点の緯度経度を利用しています。

なお緯度経度の情報および十進表記は下記のサイトの情報を使いました

http://user.numazu-ct.ac.jp/~tsato/webmap/sphere/coordinates/advanced.html

関数内容
ST_GeoHash()緯度経度の値またはPOINT型の値からGeoHash値を生成
ST_LatFromGeoHash()GeoHash値から緯度を算出
ST_LongFromGeoHash()GeoHash値から経度を算出
ST_PointFromGeoHash()GeoHash値から緯度経度を算出しPOINT型の値を返す
# 横浜スタジアム ホームベース付近 北緯35°26′35″ 東経139°38′25″ 
# 十進表記 北緯35.442972 東経139.640223

mysql> SELECT
    ->  ST_GeoHash(139.640223, 35.442972, 4) AS GeoHash4,
    ->  ST_GeoHash(139.640223, 35.442972, 32) AS GeoHash32;
+----------+------------------------+
| GeoHash4 | GeoHash32              |
+----------+------------------------+
| xn73     | xn739s4ym0c53e0pys2c9g |
+----------+------------------------+
1 row in set (0.01 sec)

mysql> SELECT
    ->  ST_LatFromGeoHash(ST_GeoHash(139.640223, 35.442972, 4)) AS GeoHash4,
    ->  ST_LatFromGeoHash(ST_GeoHash(139.640223, 35.442972, 32)) AS GeoHash32;
+----------+-----------+
| GeoHash4 | GeoHash32 |
+----------+-----------+
|     35.4 | 35.442972 |
+----------+-----------+
1 row in set (0.00 sec)

mysql> SELECT
    ->  ST_LongFromGeoHash(ST_GeoHash(139.640223, 35.442972, 4)) AS GeoHash4,
    ->  ST_LongFromGeoHash(ST_GeoHash(139.640223, 35.442972, 32)) AS GeoHash32;
+----------+------------+
| GeoHash4 | GeoHash32  |
+----------+------------+
|    139.7 | 139.640223 |
+----------+------------+
1 row in set (0.01 sec)
# 横浜駅きた西口 北緯35°28′2″ 東経139°37′23″
# 十進表記 北緯35.467360 東経139.623148

mysql> SELECT
    ->  ST_GeoHash(139.623148, 35.467360, 4) AS GeoHash4,
    ->  ST_GeoHash(139.623148, 35.467360, 32) AS GeoHash32;
+----------+----------------------------------+
| GeoHash4 | GeoHash32                        |
+----------+----------------------------------+
| xn73     | xn73c0wkr5j52nh2eub7y5bpbpbpbpbp |
+----------+----------------------------------+
1 row in set (0.00 sec)

mysql> SELECT
    ->  ST_LatFromGeoHash(ST_GeoHash(139.623148, 35.467360, 4)) AS GeoHash4,
    ->  ST_LatFromGeoHash(ST_GeoHash(139.623148, 35.467360, 32)) AS GeoHash32;
+----------+-------------------+
| GeoHash4 | GeoHash32         |
+----------+-------------------+
|     35.4 | 35.46736000000001 |
+----------+-------------------+
1 row in set (0.01 sec)

mysql> SELECT
    ->  ST_LongFromGeoHash(ST_GeoHash(139.623148, 35.467360, 4)) AS GeoHash4,
    ->  ST_LongFromGeoHash(ST_GeoHash(139.623148, 35.467360, 32)) AS GeoHash32;
+----------+--------------------+
| GeoHash4 | GeoHash32          |
+----------+--------------------+
|    139.7 | 139.62314800000001 |
+----------+--------------------+
1 row in set (0.00 sec)

ハッシュ長を4桁にした場合は情報が丸められ、同じ緯度経度の情報になっています。プライバシー保護などの観点から、正確な位置を利用するのではなく大まかな場所やエリアで表示させるなどに利用できそうです。

2016-05-18

mysqlクライアントプログラムによるSQLコマンドとMySQL ShellでのJavaScriptベースのコマンドの比較

| mysqlクライアントプログラムによるSQLコマンドとMySQL ShellでのJavaScriptベースのコマンドの比較を含むブックマーク

2016年10月1日 MySQL 5.7.15 + MySQL Shell 1.0.5にて検証のうえ、コマンドおよび一般ログの出力内容更新済み

MySQL 5.7.12のリリースと同時に登場したMySQL Document Storeとそれに関連するX Dev APIMySQL Shellについて、既存のSQLとの関係をMySQL 5.7.125.7.15にて一般ログの出力を見ながら簡単に調べてみました。

初期設定等はここ↓ここに詳しく書いてあります。

MYSQLXとMYSQL SHELL初期設定と基本動作確認

基本操作はこちらにも書かれています。

MySQL Shell / X DevAPI / X Protocol - @tmtms のメモ

なお一般ログの出力からは日時、クライアントのIDおよびQueryの文字は削除してあります。

2016-05-18T02:50:58.045435Z   13 Query	SELECT DATABASE()
↓
SELECT DATABASE()

カレントデータベースの変更

mysqlクライアントからのSQLMySQL Shellのコマンド
コマンド

mysql> USE x_sample;

Database changed

mysql-js> db = session.getSchema('x_sample');

<Schema:x_sample>

一般ログ

SELECT DATABASE()

Init DB x_sample

show databases like 'x_sample'

SHOW TABLES FROM `x_sample`

SELECT C.table_name AS name, IF(ANY_VALUE(T.table_type)='VIEW', 'VIEW', IF(COUNT(*) = COUNT(CASE WHEN (column_name = 'doc' AND data_type = 'json') THEN 1 ELSE NULL END) + COUNT(CASE WHEN (column_name = '_id' AND generation_expression = 'json_unquote(json_extract(`doc`,''$._id''))') THEN 1 ELSE NULL END) + COUNT(CASE WHEN (column_name != '_id' AND generation_expression RLIKE '^(json_unquote.(.?)?json_extract.(.?`doc`,''.$.?(...?[^[:space:][...+)+''.).?{1,2}$') THEN 1 ELSE NULL END), 'COLLECTION', 'TABLE')) AS type FROM information_schema.columns AS C LEFT JOIN information_schema.tables AS T USING (table_name)WHERE C.table_schema = 'x_sample' GROUP BY C.table_name ORDER BY C.table_name

テーブルおよびコレクションの作成

mysqlクライアントからのSQLMySQL Shellのコマンド
コマンド

mysql> CREATE TABLE `x_sample`.`tbl_sql` (id SERIAL, doc JSON) CHARSET utf8mb4 ENGINE=InnoDB;

Query OK, 0 rows affected (0.16 sec)

mysql-js> db.createCollection('tbl_x');

<Collection:tbl_x>

一般ログ

CREATE TABLE `x_sample`.`tbl_sql` (id SERIAL, doc JSON) CHARSET utf8mb4 ENGINE=InnoDB

CREATE TABLE `x_sample`.`tbl_x` (doc JSON,_id VARCHAR(32) GENERATED ALWAYS AS (JSON_UNQUOTE(JSON_EXTRACT(doc, '$._id'))) STORED PRIMARY KEY) CHARSET utf8mb4 ENGINE=InnoDB

テーブル一覧の表示

mysqlクライアントからのSQLMySQL Shellのテーブル一覧取得MySQL Shellのコレクション一覧取得
コマンド

mysql> SHOW TABLES;

+--------------------+

| Tables_in_x_sample |

+--------------------+

| tbl_sql |

| tbl_x |

+--------------------+

2 rows in set (0.00 sec)

mysql-js> db.getTables();

[

<Table:tbl_sql>

]

mysql-js> db.getCollections();

[

<Collection:tbl_x>

]

一般ログ

Query SHOW TABLES

SHOW TABLES FROM `x_sample`

SELECT C.table_name AS name, IF(ANY_VALUE(T.table_type)='VIEW', 'VIEW', IF(COUNT(*) = COUNT(CASE WHEN (column_name = 'doc' AND data_type = 'json') THEN 1 ELSE NULL END) + COUNT(CASE WHEN (column_name = '_id' AND generation_expression = 'json_unquote(json_extract(`doc`,''$._id''))') THEN 1 ELSE NULL END) + COUNT(CASE WHEN (column_name != '_id' AND generation_expression RLIKE '^(json_unquote.(.?)?json_extract.(.?`doc`,''.$.?(...?[^[:space:][...+)+''.).?{1,2}$') THEN 1 ELSE NULL END), 'COLLECTION', 'TABLE')) AS type FROM information_schema.columns AS C LEFT JOIN information_schema.tables AS T USING (table_name)WHERE C.table_schema = 'x_sample' GROUP BY C.table_name ORDER BY C.table_name

SHOW TABLES FROM `x_sample`

SELECT C.table_name AS name, IF(ANY_VALUE(T.table_type)='VIEW', 'VIEW', IF(COUNT(*) = COUNT(CASE WHEN (column_name = 'doc' AND data_type = 'json') THEN 1 ELSE NULL END) + COUNT(CASE WHEN (column_name = '_id' AND generation_expression = 'json_unquote(json_extract(`doc`,''$._id''))') THEN 1 ELSE NULL END) + COUNT(CASE WHEN (column_name != '_id' AND generation_expression RLIKE '^(json_unquote.(.?)?json_extract.(.?`doc`,''.$.?(...?[^[:space:][...+)+''.).?{1,2}$') THEN 1 ELSE NULL END), 'COLLECTION', 'TABLE')) AS type FROM information_schema.columns AS C LEFT JOIN information_schema.tables AS T USING (table_name)WHERE C.table_schema = 'x_sample' GROUP BY C.table_name ORDER BY C.table_name

データの追加

mysqlクライアントからのSQLMySQL ShellのCRUDでの通常のテーブルへのデータの追加MySQL ShellのCRUDでのコレクションへのデータの追加
コマンド

mysql> INSERT INTO tbl_sql(doc) VALUES('{"id": 1, "name": "Mike", "Team": "Products"}');

Query OK, 1 row affected (0.06 sec)

mysql-js> db.tbl_sql.insert(['doc']).values('{"id": 2, "name": "Joe", "Team": "Sales", "Title": "VP"}').values('{"id": 3, "name": "Tomas", "Team": "Development"}').execute();

Query OK, 1 item affected (0.07 sec)

mysql-js> db.tbl_x.add({"id": 1, "name": "Mike", "Team": "Products"}).execute();

Query OK, 1 item affected (0.10 sec)

mysql-js> db.tbl_x.add([{"id": 2, "name": "Joe", "Team": "Sales", "Title": "VP"}, {"id": 3, "name": "Tomas", "Team": "Development"}]).execute();

Query OK, 1 item affected (0.07 sec)

mysql-js> db.tbl_x.add([{"id": 4, "name": "Luis", "Team": "Development"}, {"id": 5, "name": "Rebeca", "Team": "Marketing"}]).execute();

Query OK, 1 item affected (0.08 sec)

一般ログ

INSERT INTO tbl_sql(doc) VALUES('{"id": 1, "name": "Mike", "Team": "Products"}')

INSERT INTO `x_sample`.`tbl_sql` (`doc`) VALUES ('{\"id\": 2, \"name\": \"Joe\", \"Team\": \"Sales\", \"Title\": \"VP\"}'),('{\"id\": 3, \"name\": \"Tomas\", \"Team\": \"Development\"}')

INSERT INTO `x_sample`.`tbl_x` (doc) VALUES ('{\"Team\":\"Products\",\"_id\":\"2ae1f178a81ce611620d5a37036c1421\",\"id\":1,\"name\":\"Mike\"}') INSERT INTO `x_sample`.`tbl_x` (doc) VALUES ('{\"Team\":\"Sales\",\"Title\":\"VP\",\"_id\":\"fc451c81a81ce611620d5a37036c1421\",\"id\":2,\"name\":\"Joe\"}'),('{\"Team\":\"Development\",\"_id\":\"28471c81a81ce611620d5a37036c1421\",\"id\":3,\"name\":\"Tomas\"}') INSERT INTO `x_sample`.`tbl_x` (doc) VALUES ('{\"Team\":\"Development\",\"_id\":\"7c7bed8ba81ce611620d5a37036c1421\",\"id\":4,\"name\":\"Luis\"}'),('{\"Team\":\"Marketing\",\"_id\":\"0c7ded8ba81ce611620d5a37036c1421\",\"id\":5,\"name\":\"Rebeca\"}')
複数ドキュメントの追加には、add()の引数としてドキュメントの配列を渡すか、ドキュメントごとにadd()にドキュメントを渡す

[add()の引数にドキュメントの配列を指定]
db.tbl_x.add([{"id": 2, "name": "Joe", "Team": "Sales", "Title": "VP"}, {"id": 3, "name": "Tomas", "Team": "Development"}]).execute();
 または
[ドキュメントごとにadd()を指定]
db.tbl_x.add({"id": 2, "name": "Joe", "Team": "Sales", "Title": "VP"}).add({"id": 3, "name": "Tomas", "Team": "Development"}).execute();

全件取得

mysqlクライアントからのSQLMySQL ShellのCRUDでの通常のテーブルへの検索MySQL ShellのCRUDでのコレクションの検索
コマンド
mysql> SELECT * FROM tbl_sql;
+----+----------------------------------------------------------+
| id | doc                                                      |
+----+----------------------------------------------------------+
|  1 | {"id": 1, "Team": "Products", "name": "Mike"}            |
|  2 | {"id": 2, "Team": "Sales", "name": "Joe", "Title": "VP"} |
|  3 | {"id": 3, "Team": "Development", "name": "Tomas"}        |
+----+----------------------------------------------------------+
3 rows in set (0.00 sec)
mysql-js> db.tbl_sql.select();
+----+----------------------------------------------------------+
| id | doc                                                      |
+----+----------------------------------------------------------+
|  1 | {"id": 1, "Team": "Products", "name": "Mike"}            |
|  2 | {"id": 2, "Team": "Sales", "name": "Joe", "Title": "VP"} |
|  3 | {"id": 3, "Team": "Development", "name": "Tomas"}        |
+----+----------------------------------------------------------+
3 rows in set (0.01 sec)
mysql-js> db.tbl_x.find();
[
    {
        "Team": "Marketing",
        "_id": "0c7ded8ba81ce611620d5a37036c1421",
        "id": 5,
        "name": "Rebeca"
    },
<中略>
    {
        "Team": "Sales",
        "Title": "VP",
        "_id": "fc451c81a81ce611620d5a37036c1421",
        "id": 2,
        "name": "Joe"
    }
]
5 documents in set (0.00 sec)
一般ログ

SELECT * FROM tbl_sql

SELECT * FROM `x_sample`.`tbl_sql`

SELECT doc FROM `x_sample`.`tbl_x`

絞り込み検索

mysqlクライアントからのSQLMySQL ShellのCRUDでの通常のテーブルへの検索MySQL ShellのCRUDでのコレクションの検索
コマンド
mysql> SELECT doc FROM tbl_sql WHERE JSON_UNQUOTE(JSON_EXTRACT(doc,'$.name')) LIKE 'Mike';
+-----------------------------------------------+
| doc                                           |
+-----------------------------------------------+
| {"id": 1, "Team": "Products", "name": "Mike"} |
+-----------------------------------------------+
1 row in set (0.00 sec)
mysql-js> db.tbl_sql.select(['doc']).where("JSON_UNQUOTE(JSON_EXTRACT(doc,'$.name')) like 'Mike'");
+-----------------------------------------------+
| doc                                           |
+-----------------------------------------------+
| {"id": 1, "Team": "Products", "name": "Mike"} |
+-----------------------------------------------+
1 row in set (0.01 sec)
mysql-js> db.tbl_x.find("name like 'Mike'");
[
    {
        "Team": "Products",
        "_id": "1436e7f2e61be611620d5a37036c1421",
        "id": 1,
        "name": "Mike"
    }
]
1 document in set (0.00 sec)
一般ログ
SELECT doc FROM tbl_sql WHERE JSON_UNQUOTE(JSON_EXTRACT(doc,'$.name')) LIKE 'Mike'
SELECT `doc` FROM `x_sample`.`tbl_sql` WHERE (JSON_UNQUOTE(JSON_EXTRACT(`doc`,'$.name')) LIKE 'Mike')
SELECT doc FROM `x_sample`.`tbl_x` WHERE (JSON_UNQUOTE(JSON_EXTRACT(doc,'$.name')) LIKE 'Mike')
MySQL ShellのCRUDでの通常のテーブルへの検索時の注意点
  • select()の第一引数は取得する列名の配列、列名はシングルクオートでかこむ
  • where()内のLIKEなどの演算子は小文字にする

MySQL Shellでクオーテーションが入れ子になる場合、シングルクオートまたはダブルクオートのいずれを外にしても問題なさそうです。
mysql-js> db.tbl_x.find("name like 'Mike'");
 または
mysql-js> db.tbl_x.find('name like "Mike"');

検索する値をパラメタ化してバインドしてもSQL的には同じ結果でした。
mysql-js> db.tbl_x.find("name like 'Mike'");
 または
mysql-js> db.tbl_x.find('name like :param').bind('param','Mike').execute();

2015-12-31

2015-09-17

MySQLの準同期レプリケーション

|  MySQLの準同期レプリケーションを含むブックマーク

MySQL 5.5での準同期レプリケーション

準同期レプリケーション自体はMySQL 5.5から導入されました。マスターー側およびスレーブ側にそれぞれ準同期レプリケーション用のプラグインをインストールし、マスターー側で rpl_semi_sync_master_enabled とスレーブ側で rpl_semi_sync_slave_enabled を有効にしておくと準同期レプリケーションが利用できるようになります。 rpl_semi_sync_master_enabled を有効にしたマスターに対して、非同期レプリケーションと準同期レプリケーションのスレーブを混在させることは可能です。

準同期レプリケーションの流れ
  1. アプリケーションからトランザクションをコミット
  2. バイナリログとストレージエンジンにトランザクション内容を記録
  3. マスターからスレーブにトランザクション内容を転送
  4. スレーブのリレーログにトランザクション内容を記録
  5. スレーブからマスターに応答
  6. マスターからアプリケーションに応答

上記の3の時点でスレーブに障害が発生しているかネットワークに問題があるなどで通信できない場合は、マスターの rpl_semi_sync_master_timeout で設定されたタイムアウトまで待ち、非同期レプリケーションと同様にスレーブの応答が無いままアプリケーションに応答を返します。この値のデフォルト値は10,000ミリ秒です。

rpl_semi_sync_master_wait_no_slaveデフォルトの ON の場合には、スレーブが一時的に切断されている場合などもタイムアウトまで待ちます。OFFに変更するとスレーブが接続されていない場合はすぐにアプリケーションに応答します。


MySQL 5.7で複数台の準同期スレーブを待つ設定

MySQLの準同期レプリケーションで何台のスレーブが応答した時点で以降の処理を継続するかはマスターの rpl_semi_sync_master_wait_for_slave_count で制御します(5.7.3以降)。 デフォルトでは1台のスレーブから応答があった段階でアプリケーションに応答します。

f:id:rkajiyama:20150917154236j:image


MySQL 5.7の"Lossless"準同期レプリケーション

従来の準同期レプリケーションでは、特定のタイミングでマスターに障害が発生した場合にデータの不整合が起こりえる課題が残っていました。上記の流れの2の時点で、別のクライアントからはコミットの内容を参照することができます。

上記の2の後でマスターに障害が発生すると、他のクライアントから見えていたコミット済みのトランザクションがスレーブには存在せず、データの整合性が取れていないように見えてしまいます。この問題を解決するのがMySQL 5.7の"Lossless"準同期レプリケーションです。

"Lossless"準同期レプリケーションMySQL 5.7から新たに加わったパラメタ rpl_semi_sync_master_wait_pointデフォルト値 AFTER_SYNC を利用することで実現できます。この値を AFTER_COMMIT に変更した場合はMySQL 5.6までの挙動になります。

"Lossless"準同期レプリケーションの流れ
  1. アプリケーションからトランザクションをコミット
  2. バイナリログのみにトランザクション内容を記録
  3. マスターからスレーブにトランザクション内容を転送
  4. スレーブのリレーログにトランザクション内容を記録
  5. スレーブからマスターに応答
  6. ストレージエンジンにトランザクション内容を記録
  7. マスターからアプリケーションに応答

f:id:rkajiyama:20150917152558j:image MySQLレプリケーション構成の模式図

※非同期レプリケーションMySQL 5.6の準同期レプリケーションではバイナリログへの記録とストレージエンジンへの変更点の記録は逐次ではなく同時


準同期レプリケーション関連のパラメタ一覧

パラメタ名設定箇所デフォルト
rpl_semi_sync_master_enabledマスターOFF
rpl_semi_sync_slave_enabledスレーブOFF
rpl_semi_sync_master_timeoutマスター10000
rpl_semi_sync_master_wait_no_slaveマスターON
rpl_semi_sync_master_wait_for_slave_countマスター1
rpl_semi_sync_master_wait_pointマスターAFTER_SYNC

2015-07-25

スカイマークがデルタ航空傘下になったとしての妄想

| スカイマークがデルタ航空傘下になったとしての妄想を含むブックマーク

妄想なので機材繰り、発着枠、政治的な観点での調整やらの細かいことは調べても無いし考えてない。あくまでも素人の妄想。

現状

   2015年9月で終了 ※※2015年10月で終了

デルタ航空傘下になったスカイマークのポイント

  1. 座席利用率LFが高い路線A330でしっかり稼ぐ
  2. 成田発着はデルタ・コネクションとしてフィーダー路線のみ運行
  3. スカイチーム加入
  4. 地方間路線は一部例外を除いて廃止

1. 座席利用率LFが高い路線A330でしっかり稼ぐ

羽田からの札幌線や福岡線はこれまでの搭乗実績としてもコンスタントに高めの数字が出ているので、A330を再度利用してより稼ぐ方向に持って行く。A330を利用再開することになればエアバスなど利害関係者からの理解&支援も得やすいのではないか。

デルタA330-200 11機、A330-300 23機運用中で後者はあと8機受領予定なので、A330の整備や訓練などデルタから支援を受けられそう。ただし現状のスケジュール上はデルタ東京線にはA330は使われていないが、名古屋 - デトロイトA330-200で運航されている。太平洋路線だとソウル - シアトルロサンゼルス上海 - シアトルミネアポリスあたりにA330-300、北京路線香港 - シアトルA330-200が入っている。


2. 成田発着はデルタ・コネクションとしてフィーダー路線のみ運行

スカイマーク単独だと成田線の搭乗実績は惨憺たる数字で結局撤退。日本におけるデルタ・コネクションとして、コードシェアまたはデルタ便名での運行を前提とし、海外からの乗り継ぎ客を取り込むことでLCCとは違った位置づけとなってそれなりの搭乗率が期待できるのではないか。デルタが就航予定の成田 - 関西線成田 - 神戸にしてスカイマークで吸収することができなくはなさそう。

羽田線と共通の就航先に限定することで機材繰りや拠点でのコストの最適化ができそう。運航はデルタに乗り継ぐ客のための15時着18時発前後の便に限定。ただ内際乗り継ぎなので早め到着遅め出発が必要となるとすると成田に4,5時間留め置くことになり、もったいなければ間合い運用で近距離に飛ばすかが微妙。

参考:2013年10月の成田発着の搭乗実績

旭川:28.8%、札幌/千歳:51.2%、福岡:40.2%、沖縄/那覇:54.1%、石垣:29.6%

中部は主にデトロイト線へのフィーダーとして何路線か若干の搭乗率向上が狙えそう。


3. スカイチーム加入

ラウンジ設置が多少課題になりそうなものの、クレジットカード会員のラウンジなどを利用できればどうにかなりそうだし、エリート会員特典とかはデルタからまるごとコピーすればなんとかなりそう。

スカイチーム  加盟に必要な条件

各地から東南アジア方面や逆に成田 - 札幌への乗り継ぎのレジャー需要ありそうだし、エールフランスJAL国内線コードシェアしているのでそれを奪い取れればそれなりに成り立ちそう。KLMがその昔JASコードシェアしていた国内線なんかも。中台韓のスカイチーム各社は割と全国各地に就航しているので国内線への乗り継ぎ需要はあまり高く無さそう。

参考:エールフランスによるJAL国内線でのコードシェア

東京/成田 - 大阪/伊丹名古屋/中部、札幌/新千歳福岡東京/羽田 - 長崎大阪/関西 - 札幌/新千歳


4. 地方間路線は一部例外を除いて廃止

米子仙台はすでに撤退決定。茨城も搭乗率が低くデルタスカイチームとのシナジーもないのでおそらく撤退になりそう。間合い運用で飛ぶなり地方間で残す路線も、能登空港搭乗率保証制度のような就航先自治体からの補助金があるところに限定することになるのが現実的か。

「関西の拠点」として格納庫まで整備しちゃった神戸空港からは、現状で60%以上の搭乗率が見込める路線を残すかどうかがポイントになりそう。


想定される就航先と路線の案

以上を踏まえて確定といえる空港は羽田成田に加えて、搭乗実績とフィーダー路線としての需要から新千歳福岡那覇、それに中部ぐらいか。

デルタ中心でスカイチーム加入前提で再建計画を立てたら、インバウンド旅客利便性も上がるし3アライアンスの航空各社が競争することで全体的なサービス改善が進んだら良いのではないかと個人的には結論。航空会社の再建になるとどうしても地方路線からの撤退が課題になるけど、リンクが就航前に破綻したみたいに簡単な話でないことは確か。