2015年8月25日火曜日

MySQL使いの人がPostgreSQLを始めるときの罠をまとめてみた

昨日書いたエントリがなかなかいい感じに拡散された。

MySQL使いが知るべきPostgreSQLとの違いと変わらない一つのこと


で気付いた。
多分本当にMySQL5.7の罠が理由でPostgreSQLに移行する人は上のエントリを求めてない。
つまり本来ターゲットにすべき人は


  • SQLはORMが解決してくれるから違いなんて気にしない
  • ロジックはSQLではなくアプリケーションコード側が行う
  • DBはデータを置くストレージだ、いいね?


みたいな人だ。
前述のエントリでよしPostgreSQL使おう!!って人は多分MySQL使っても乗り越えていける人たちだ。
勿論そんな人達がPostgreSQLに来てくれるのは嬉しいし大歓迎。
それとは別にもっと窓口を拡げるために必要な移行時の罠をまとめておく。
これはMySQLと比較しながらPostgreSQLの事を書く。
だが初めてPostgreSQLを触る人は知っておいた方が良いことのまとめになるはずだ。


1. DBを作成するときの罠


一番最初にPostgreSQLをLinux等にインストールすると
service postgresql-9.4 initdb
をまずはすると思う。
その場合、PostgreSQLのデフォルトのロケールはOS側に設定されているロケールを使用する
つまり多くの場合は

ja_JP.UTF-8

となる。
これに伴いDBが壊れるということはない。
ただしソート順に影響する。
具体的には

日本語ロケールでは辞書順(カタカナ→ひらがな, 清音→濁音→半濁音) の順にソートされる

のだ。
多くのシステムの場合、これは想定外のソート順になる。
そのためDBを作成する際には

service postgresql-9.4 initdb --locale=C

service postgresql-9.4 initdb --no-locale
を指定することになる。
どちらも同義である。
こちらを行うことにより文字のバイナリ値を基準にしたソートになる。
絵文字でソートしたい場合も安心だ。
詳しくは下記のエントリを参考にして欲しい。

ロケール(国際化と地域化)



2. アクセス制御の罠


MySQLに対するアクセス制限はmy.cnfに
bind-address = 127.0.0.1
と書いたりMySQLのuserテーブルで指定したりする。
それに対し、PostgreSQLはDBをインストールしたフォルダ内のpg_hba.confで制御する。
こちらについては先日紹介したとみたさんのエントリでも紹介されている。

MySQLユーザーがPostgreSQLを触ってみたメモ


その際に気をつけてほしいことがある。
それはMETHODの指定である。

host    all    all    192.168.0.0/24    trust
としてあったとする。

これは192.168.0.1~192.168.0.255のIPアドレスからのアクセスはパスワード認証無しでアクセスできる設定だ。
もしこのDBが外に晒されており、全てのIPを表す0.0.0.0/0を指定した場合は自由にアクセスできる事になる。
PostgreSQLはdefaultでスーパーユーザーとしてpostgresというユーザが作成される。
この状態でpostgresユーザでアクセスすれば...結果は明白である。
笑い事に聞こえるかもしれないがEC2やVPSでDBを作っている場合に一時的にtrustを指定する人を見かける。
そして設定は明示的にに読み込みを行わなければならない。
ここに大きな罠があり


  1. 確認のためpg_hba.confに0.0.0.0/0 trustを指定して起動。
  2. テスト終了後、pg_hba.confを修正
  3. 再起動時や再読み込みを忘れる


とするとpg_hba.confは正しいのに誰でもアクセス出来る状態のままとなる。
せめてmd5を指定するようにしよう。

host    all    all    192.168.1.1/32    md5

詳しいpg_hba.confの説明等は公式documentを読んで欲しい。

19.1. pg_hba.confファイル


なお蛇足だがそもそもpostgresql.confの設定で

listen_addresses = '*'

を指定しないとdefaultではlocalhost以外からアクセス出来ない。
設定箇所が2箇所あるので要注意だ。


3. テーブル作成時の罠

MySQLからPostgreSQLに移行した時、仮にpgadmin3を使って型を指定しようとしたら驚くだろう。
余りにもデータ型の種類が多いからだ。
データ型についてはまず公式documentのリンクを紹介しておく。

第 8章データ型


君たちが欲しいのは


  • 数値型
  • 文字列型
  • 日付/時刻型


だと思う。
それぞれについて簡単に解説しておく。

●数値型

通常は


  • bigint  8byte整数
  • integer  4byte整数
  • smallint 2byte整数
  • numeric  MySQLのDECIMAL相当
    (MySQLではnumericはDECIMALのエイリアス)


で事足りると思う。
ただPostgreSQLにはこの他に論理値データ型として


  • boolean  1byte


がある。
勿論入るのは0 or 1 or NULL(許可した場合)だ。
SQLとしてはtrue or falseでもよい。
他にも柔軟に受け入れるので使う場合は公式documentをチェックされたい。

論理値データ型


そしてサロゲートキーを使いたい場合にMySQLはAUTO INCREMENTを指定すると思う。
AUTO INCREMENTはPostgreSQLには無い
その代わりシーケンスを作り、該当の整数型のdefaultにnextval(シーケンス名)を指定することで同義になる。
とは言ったもののその手順は煩雑だ。
そのため最初から


  1. 整数型の指定
  2. シーケンスの作成
  3. 該当シーケンスをdefaultに指定


を全て丸めてやってくれる型がある。
それがserial型だ。


  • bigserial   →  bigint
  • serial     →  integer
  • smallserial  →  smallint


なおPostgreSQLのシーケンスは最大値に行った場合にCYCLEの指定の有無で周回するか決まる。
CYCLEを指定しない場合はNO CYCLEとなり周回せずにエラーが発生する。
だがserial型で作った場合はCYCLEが指定されない=最大値になるとエラーが発生する。
また自分で設定すれば連番の取得の昇降やSTEP、MAXやMINも指定できる。
CYCLEを指定して周回するIDも作れる。
またAUTO INCREMENTと違い複数テーブル(またはカラム)からも参照、指定することが出来る。
シーケンスはMySQLには無い概念なので一度調べてみると設計の幅が広がるのでオススメだ。

●文字型

PostgreSQLの文字列型は


  • character varying 可変長
  • varchar      character varyingのエイリアス
  • character     空白を埋める固定長
  • char        characterのエイリアス
  • text        制限なし可変長


となる。
実際は可変長、固定長、制限なしの可変長だ。
多くの運用の場合、固定長を使うメリットがない。
なので可変長のcharacter varying(以下varchar)かtextを使うことになる。
またvarcharとtextの違いは制限の有無のみだ。
そのため参照速度だけで言えば制限のオーバヘッドの少ないtextの方が早い
また制限する場合は


  • varchar(n)


とnを指定することになるがnは文字長(文字数)だ。
バイトでは無いので注意が必要だ。
(MySQLの場合のVARCHARはバイト数)
(MySQLも文字数だった、yoku0825さんご指摘あざます!!あと誕生日もおめざす!!)



仕様として標準SQLに準拠しているのだがそもそも標準SQLの仕様に癖がある。
一度公式documentを拝読しておくと救われるかもしれない。

8.3. 文字型


またMySQLとの大きな違いとしてPostgreSQLの文字列型は文字の大小を区別する
('A' != 'a'である)
つまりMySQLのBINARY属性を指定した状態と同じ挙動である。
文字列に関してはMySQLと大きく違う仕様が多いので注意が必要だ。
(これは逆も然りでPostgreSQL使いがMySQLを使う際に多くの人がこの罠にハマる)
蛇足としてPostgreSQLの多くの関数は文字列を受け付ける際はvarcharを指定してもtextにCASTされる。
そういった理由からよく文字列型は全てtextを指定する設計も見かける。
その場合は不正なデータを入れられた時の予防やディスク容量計算が難しくなる。
適正な型指定はデータを守るのでCHECK制約と合わせて使いわけよう。
更にPostgreSQLには列挙型(enum)もある。

8.7.1. 列挙型の宣言


(MySQLにもEnumがあるらしい)



CHECK制約とは違いデータにソート順を持たせることが出来る。
覚えておいて損はないだろう。


●日付/時刻型

日付/時刻型は

  • timestamp  日付と時刻両方を持つ 例:2015-01-01 00:00:00
  • date     日付を持つ(時刻無し) 例:2015-01-01
  • time     時刻を持つ(日付無し) 例:00:00:00
  • interval   時間間隔       例:1 year 2 months 3 days 4 hours 5 minutes 6 seconds

がある。
timestampはMySQLのdatetime相当だ。
timestampとtimeについてはtime zoneを持たせることが出来る。
(これによりMySQLのtimestampを表現することが出来る)
指定した場合はUTCとして内部で持ち、表示の際に設定されたタイムゾーンに合わせて計算してくれる。
国内で使う場合はタイムゾーンを指定しないtimestamp without time zoneで問題ない。
またMySQLのtimestampのdefaultのようにUPDATE文の対象になった際に自動的に対象レコードの指定columnをCURRENT_TIMESTAMPで更新する機能は無い。
同じようにしたい場合はトリガーを書くことになる。
これは非常に便利なのでPostgreSQLにも欲しいところだ。
またintervalについては癖の強い型だ。
そのほかの日付/時刻データ型と合わせて公式documentを見ていただきたい。

8.5. 日付/時刻データ型



●配列型と範囲型

補足としてPostgreSQLは配列型と範囲型がある。
どちらも強力な機能だが乱用は毒にもなる。
公式documentと例を上げているエントリを紹介しておく。



4. ORMの罠

RoRを使う人は問題ないがPHPerはFrameworkのORMが対応してないことがある。
まさにFuelPHPの話だ。
私は標準のクエリビルダをラッパーし自作ORMを作成しているがこれは万人向けではない。
そのため、もしPostgreSQLに対応したORMが必要な場合はDoctrine2をオススメする。
ただし悲しいことに公式documentは英語しかない。
しかしDoctrine2はSymfony2のORMだ。
そのためSymfony2の公式documentを読むことで使い方を知ることが出来る。

Symfony2


FuelPHPでインストールする場合はComposerに対応しているので安心して欲しい。

FuelPHPでdoctrine2を使ってみた


またDoctrine2を利用すればスキーママイグレーションも出来る。
(FuelPHPの標準のスキーママイグレーションはMySQL専用なので動かない)



ここまで来た君は手元のアプリケーションからDBに接続し、自由にテーブル設計できたはずだ。
長くなったので今日はここまでとする。
この後、運用で困った事があればメーリングリストで聞いてみるといい。
きっと誰かが答えてくれるはずだ。

PostgreSQLユーザ会 メーリングリスト


それでは検討を祈る。

2015年8月24日月曜日

MySQL使いが知るべきPostgreSQLとの違いと変わらない一つのこと



私が尊敬してるDBスペシャリストの@yoku0825さんがこんな事言ってた。



@yoku0825さんはMySQLのスペシャリスト中のスペシャリストだ。
その@yoku0825さんがこんな事を言うなんて只事じゃない!!
で話になった元ネタはコレ。

日々の覚書: #yapcasia でMySQL 5.7の罠についてLTしてきました


要はMySQL5.7は「目指している正しい姿」になるために下位互換性を幾つかを捨ててるよって話だ。
その中には360日問題があるけどそれ言うと正しさとは?みたいな話になるので今回は話題にしない。
(デフォルトでパスワードが360日後に無効になるという仕様がデフォルトになったという話)
MySQLを使ってる人は@yoku0825さんのブログを一読したほうがいい。
必ず知らなかった罠が幾つか見つかると思う。
そのツイート見て



とブーメラン投げて見事に刺さってるので今から記事書く。
両サイドにはかなり厳しい話もするが俺の本音を聴いておけ(関白宣言)
まぁ歴史の長いRDBなのでお互いの比較記事は沢山ある。
なのでマルチスレッド(MySQL)とマルチプロセス(PostgreSQL)だとかVACUUMだって話はしない。
むしろ実際に使ってみた際の違いをにフォーカスする。

1. SQLの違い


基本的にMySQLでやっていたことはPostgreSQL出来る。
しかし関数の挙動の違いは幾つかある。
例えば時間から曜日に該当する数字に変換した場合に


  • MySQL → date_format(time,"%w") 0から始まり、日曜日に該当する
  • PostgreSQL → to_char(time,'D') 1から始まり、日曜日に該当する


など挙動に互換性がない場合も多い。
関数を使う場合は一度仕様を確認した方がいい。
幸い、PostgreSQLは有志によって日本語ドキュメントが充実している。
今はGithubで管理されてるので誤字脱字、表現の曖昧さなどはプルリクエストすることが出来る。

PostgreSQL日本語ドキュメント




MySQLを使ってた人はPostgreSQLを使うことでWindow関数など新たに知る機能が多いだろう。
MySQLしか触ったことが無く、OracleやMSDB等を触ったことが無いなら一度SQLの勉強をした方がいい。
必ず業務を効率化してくれるはずだ。
SQL勉強する人向けには最近読んだ本でPostgreSQLベースで書いてあって読みやすかった本をオススメしとく。



じゃあPostgreSQL優秀じゃん!大は小を兼ねるじゃん!!と言いたいところだがMySQLにしか無い文法もある。
MySQLにもPostgreSQLにもMerge文はSQL標準なのに実装されてない。
しかしMySQLには代替案として




がある。
これに準ずる機能はPostgreSQLには無い。
しかしWITH句とRETURNING句(MySQLには無い機能だね)を使えば一応PostgreSQLでも表現出来る。
第九回 中国地方DB勉強会 in 米子でこの話題は取り上げたので興味がある人は資料を見て欲しい。
このリンクの先に梶山さんのMySQL5.7の話が出てるのでそっち見て欲しい、いや見たほうが良い、絶対見るべきだ。
ただ事ある毎にPostgreSQLにMerge文相当が無いことをDis指摘していたら遂に9.5からそれ相当の構文が実装された。
これはMySQLの「INSERT...ON DUPLICATE KEY UPDATE構文」と似た構文で実装されている。

INSERT ... ON CONFLICT {UPDATE | IGNORE}構文


PostgreSQL9.5に興味が出た人はリリース予定の機能が以下にまとまってる。

What's new in PostgreSQL 9.5(英語)


英語なんて読めるか!って人は下記のブログをcheckするといいだろう。

日々の記録 別館


Twitterで行われるラーメン飯テロに耐えれるなら著者のぬこさんをフォローするのもいい。
あとはみかかな人たちが頑張ってるのでSlideShareをWatchすると幸せになれるかもしれない。
オススメのSlideShareのリンクを貼っておく。

10大ニュースで振り返るPGCon2015


おっと話が大分脱線してしまった。
話を戻すがPostgreSQLのSQLは


  • 文字結合が||で出来る
  • 日付操作がday +1で出来る


などどちらかと言えばOracleを意識した記述も多い。
ただ悪名高き(+)は無いしNULL = ""も無いのでそこは安心して欲しい
なのでわかりやすく例えるとしたら

ザ・キング・オブ・ファイターズの95の京と96の京くらい違う


といったところか。
新日本企画が産んだ名作格ゲー、ザ・キング・オブ・ファイターズを知らない若者は

細かいところは違うけど大体一緒でPostgreSQLの方が痒いところに手が届きやすい


くらいのニュアンスで居るといい。
つまりSQLに関してPostgreSQLに乗り換えて不満が出ることは少ないだろう。


2. 機能の違い


これもPostgreSQLの方が多い。
まずマテリアライズド・ビュー(以下マテビュー)がPostgreSQLにはある。
簡潔に言うとviewの結果を実体としてキャッシュするというものだ。
これでtmp_hogeみたいな中間テーブルを作る必要は無くなる。
ただし銀の弾丸ではない
乱用するとCPUやHDDリソースなどが死ぬ。
そのほかにもCHECK制約があるがこのへんはMySQLで慣れた人には使うシーンが想像出来ないと思う。
データにバグやヒューマンエラーで不正なデータが入って苦しんだ人は覚えておくいい。
次の新規設計時にDBがデータを守ってくれる。
どちらかと言えば


  • JOINのアルゴリズムが複数ある
  • 相関サブクエリが早い


と言う点がMySQLと比較すると直接的にパフォーマンスが上がりメリット感じるところだろう。
ただしUPDATE文に関してはPostgreSQLの方が遅い(場合が多い)
これは追記型アーキテクチャの壁なのでMySQLの方が有利な点だ。
しかしガンガンUPDATEを走らすようなシステムはロックを必要とするはずでロック待ちの方が速度に影響およぼす。
そのため直接的に問題になることは少ないはずだ。

さてここまで話をしたのはPostgreSQLの良いところだ。
勿論MySQLの方が有利な機能もある。
それはレプリケーションだ。
そもそも論としてMySQLとPostgreSQLはアーキテクチャが違うのだがPostgreSQLには自動フェイルオーバーはない。
PostgreSQLの場合はPacemakerなどのサードパーティを利用して実現することになる。
corosyncに苦い思い出がある人は機会があれば一緒に飲もう。
また自動フェイルオーバーはMySQL5.6からの機能だ。
MySQL5.6をまだCHECKしてない人は奥野さんのブログを見るといいだろう。

開発スピードアクセル全開ぶっちぎり!日本よ、これがMySQL 5.6だッ!!


とは行ってもPostgreSQLのレプリケーションに対する投資は素晴らしく今は追いつきつつあると行っても過言ではない。
以上の通り機能面でもSQLと同様の事が言える。
ここも安心してPostgreSQLを推せる内容だ。


3. GUIツールの違い


ここからはPostgreSQLのダメな所になる。
正直言ってPostgreSQLの管理や設定を一つのGUIで全て行うのは諦めた方がいい。
まずSQLエディタ(DBAツール)だがMySQL使いはWorkbenchを使ってると思う。
基本無料なので使ってない人は是非使った方がいい。
それに対してPostgreSQLはpgAdmin3になる。
残念ながら使いやすいとは言い難い。
例えばMacOS版は日本語入力がインラインではない。
この時点でリュウが使ったら殺意の波動に目覚めるレベルだ。
カプコンが産んだ名作、ストリートファイターを知らない若者はウメハラの背水の陣を見ておくといい。
そしてpgAdminは大切な場面で度々落ちる。
エクセル方眼紙を彷彿させると言えば共感してくれる方も多いだろう。
とにかく、PostgreSQLのGUI関連は弱い。
周囲に聞くとみんなコマンドラインの黒い画面でpsqlを直接操作しているらしい。
なので不満がコミュニティからあまり出ていないようだ。
しかし私は補完が利かない環境での開発は耐えれない若者なので代替案として以下のツールを使ってる。




どちらも無料で使え、ER図をリバース・エンジニアリングしたり出来る。
しかもPostgreSQLもMySQLにも繋げれるのでオススメだ。
0xDBEはIDEを開発してるJetBrains製でMacOSでもWindowsでも動くので是非試して欲しい。
A5:SQL Mk-2はmatsubaraさんが個人で開発されてる。
日本語だしExcelにテーブル定義書をリバース・エンジニアリング出来る。
これが無料なのが信じれないレベルのクオリティだ。
なおphpMyAdminに対抗したphpPgAdminも一応ある。
インストールしないことをオススメする。
とモダンなUIとは程遠いPostgreSQLだがPythonでpgAdmin4を作るという話が進んでる。
これがキラーアプリになってくれることを切に願っている。

4. ハードウェアでの違い


長くなってきたので簡潔に言う。
PostgreSQLはMySQLと違ってSSDにしたからといって何十倍の速度も出ない
(せいぜい数倍程度)
さらにFusion-ioは特にMySQLに特化してるのでその差は顕著だ。
PostgreSQLはHDDに特化してシーケンスに書き込もうとするのでそのオーバーヘッドの差が大きい。
もし、金の弾丸でPostgreSQLを殴るときはまずはメモリを増やそう。
PostgreSQLに限らずRDBの多くの問題は金で殴ってメモリを増やすと解決することが多い。
それでもダメな場合は優秀なDBエンジニアを用意しよう。
PostgreSQLはハードウェアを金で殴りにくいのは事実だ。

5. クラウド上での違い


やっとAWS RDSにPostgreSQLが去年追加された。
しかしまだ日本語の全文検索拡張はインストール出来ないしAuroraのPostgreSQL版も無い。
だがHerokuを初め、標準的な使い方であればPostgreSQLをsupportしてるところも出てきた。
国内だとニフティがRDSとしてPostgreSQLをサービスしている。
このへんはOSC 沖縄の時に話をしたので興味がある人はそちらを参考にして欲しい。

OSC沖縄でクラウドの選び方の話で登壇してきたので資料を公開する





随分と話が長くなってしまった。
本当はPostgreSQLには


  • PL/SQLの代わりにPL/PythonやPL/JavaScriptが使える
  • 外部テーブルラッパー(FDW)を使えばPostgreSQLのtableのようにMySQLを参照できる
  • MySQLと違いトリガーを行単位とクエリ単位が選べる(MySQLは行単位のみ)


などの話もしたかったがこのへんの話はまた別の機会にしようと思う。
なお、全然実践的じゃなかったし本当にMySQL派の人がPostgreSQLを使うときのハマリどころは皆無だった。
そこでお詫びにとみたさんの記事を紹介する。



最後になるがMySQLとPostgreSQLはライバル同士だ
しかしながらコミュニティ間はフレンドリーそのものだ。
他にライバル同士がこんなにフレンドリーなOSSコミュニティはあるのだろうか。
実際に合同勉強が開かれたりもする。

MyNA・JPUG合同DB勉強会 in 東京を開催してきた(FDWの話もしてきた)


私はそういうところがRDBのOSS界隈の好きなところである。
これを読んで興味を持った人は是非、DBのコミュニティに参加して欲しい。
MyNAもJPUGも暖かく迎えてくれるだろう。
それはどちらのコミュニティも変わらないことだ。


#### 2015/08/25追記 ####

好評だったので第二弾も作った

MySQL使いの人がPostgreSQLを始めるときの罠をまとめてみた

2015年8月10日月曜日

IoT時代を生き残るためにIPを扱うならPostgreSQL!!

皆様、時代はIoTと言われてますがIPv6使ってますか?
IPv4でも面倒くさい色々と苦労はあったと思います。
ですがIPv6になると

  • ソートとか大変(文字列ソートではダメ)
  • 検索とかもっと面倒くさい(範囲の検索とか)
  • 特定のIPの次のIPを取得するの面倒くさい(IPのインクリメントでの払い出しとか)

などIPv4の時に苦労した事がIPv6ではもっと大変になります。
例えばPHPだとip2long()って関数がありますがIPv6は非対応です。
なぜかと言うとIPv6だとlongに入り切らないからね!!
そうなるとソートとかインクリメントとか工夫が必要になります。
ですがPostgreSQLのネットワークアドレス型を使うと良きに計らってくれます。
ソートや検索はORDER BYやWHEREでOK!
インクリメントについては

SELECT '192.168.0.1'::inet + 1


とするとちゃんと"192.168.0.2"を返してくれます。
勿論IPv6にも完全対応!!

SELECT '2001:0db8:0000:0000:3456:0000:0000:0000'::inet + 1


"2001:db8::3456:0:0:1"が帰ってきます!
見ての通り省略記法にも対応されてます。
検索も内包を

SELECT inet '192.168.1.5' << inet '192.168.1/24'


と表現できます!!
(この場合は含まれるのでTRUEが返ってきます)
勿論WHEREに

SELECT * FROM ip_address
WHERE ip << inet '192.168.1/24'

のような記述で書けます! 他にも色んな書き方ができるので是非公式ドキュメントを一読してみてください。

公式ドキュメント

と言うことでこれからIoTに関わるとネットワークを管理する必要が増えてくると思います。
そのときは是非ともPostgreSQLを使ってみてください。

餃子の皮から作るか既成品を買って来るかの話

弊社は素晴らしいCのプログラマばかり。
僕はほとんどCを書かずLLの甘えた環境で富豪プログラミングするので社内で良くディスカッションになることがある。
それは

  ◯◯を0から作るか外部から持ってくるか

という話。
◯◯はLibraryだったりサービスだったり色々あるのだけど僕は車輪の再開発は極力しない派。
Libraryの学習コストを含めても0から作るより持ってきたほうが良い品質で早く出来るから。
でも社内では時々で0から作ったほうが早い(納期も速度も)という話が出てくる。
たしかに既存のLibraryをラッパーしたりそれを改修したりするぐらいなら作りなおした方が早いこともあるのだけど「正気か?」みたいな規模の時でも発生する。
しかも事実彼ら(Cプログラマ)はほぼ当初の予定通り工数で仕上げてくる。
この現象についていい名前無いかなぁって話をオープンセミナー香川の懇親会で話をしたら@blue48さんが

「それはね、餃子の皮だよ」

と表現して感銘を受けた。
確かに職人はスーパーに言って餃子の皮を買って来るより自分で作ったほうが早いし美味い。
逆に俺みたいなパンピーは餃子の皮を買ってきたほうが早いし美味い。
どちらが正しいとかじゃなくて餃子に関して言えば

・前者はそこでしか食べれないクオリティの高い餃子を提供できる
・後者は安い早いそこそこ美味い餃子を提供できる

なので方向性の違い。
でその方向性の違いなんだけどエンジニアにもそれは言えるよなぁと。
つまりは自分が何処でスペシャリティを発揮するか。

そうやって自分のエンジニアとしてのポジションを振り返った時に色々思うこともあるなぁと言うお話でした。

なお、妻は餃子の皮は作る派です。