nelmoの日記帳

エンジニア見習いの備忘録とかです。

2019年総括

2019年は仕事・私事ともにいろいろあったので珍しく総括的なブログを書いておきます。

仕事的な話

ブログには書いていませんでしたが2018年6月に前職を辞め、2018年7月からArm Treasure Data株式会社のSolution Engineerとして働いています。本社はMountain Viewで、東京オフィスは丸の内にあります。

www.treasuredata.co.jp

前職には4年9ヶ月在籍していました。たくさんの迷惑をいろいろな人にかけましたが、本当に良い会社に良いタイミングで働けたことに心から感謝しています。

Arm Treasure DataはTreasure Data Customer Data Platform(CDP)というブランドで製品を展開しています。私の仕事は日本のお客様に対するテクニカルプリセールス、ならびに導入支援からお客様のゴールを最終的に実現させるための伴走がメインですが、自社のプロダクトの改善のためにUSのプロダクトチームやエンジニアチームとも日々ディスカッションをしています。技術的な要素はもちろん、営業的側面やプロダクト戦略の理解など、それなりに幅広い知識が求められる守備範囲の広い仕事だと思ってます。

Solution Engineering以外の部門でも積極的に採用かけていますので、興味がある方はご連絡ください。お話しながらご飯食べましょう。

www.treasuredata.co.jp

英語の話

英語に関しては最初は本当に大変でした。1年半経ったいま、感覚的には苦しいけどなんとか仕事になるレベルまでは到達したかなと思っています。グローバル企業のクライアントを担当したりすると日本国内のミーティングでも英語でプレゼンしなければいけなかったり、製品仕様の資料を英語で書く必要があったりするわけで、そういった訓練を通じて叩き上げられた感覚です。

英会話はGABAに今年の1月から一年間通いました。75レッスンで入学金なども合わせて合計50万円弱。

www.gaba.co.jp

オンライン英会話にしなかったのは

  1. 回線越しだとコミュニケーションとりづらそうで不安
  2. 前にレアジョブの無料レッスンを受けたが、基本的にはテキストベースの進行で自分の苦手部分の解消になるかわからなかった が理由です。

1年間のレッスンを終えた結果、来年は方針転換してオンライン英会話レッスンに通おうと考えています。前述の理由1に関しては、そもそも仕事でもオンラインMTGは多いので不安定な回線にも慣れておかなければだめだよね、という点。2番目はオフラインの講習でも特に変わらないと感じた点です(これは私からもっと講師へのリクエストをすべきだったね、という反省はあります)。この2点を踏まえた上で、結果的に支払うコストに見合わないかなという感想でした。

オンライン英会話、どこにしようかはまだ考え中なのでオススメがある方は教えていただけるとと喜びます。

アウトプット

今年の4月にはSA Night #1というイベントで仕事内容について発表しました。

connpass.com

当日の私のスライドがこちら。

www.slideshare.net

自分を含めた発表者の4名がかなり似た角度の話をしているのを聞いて、自分の仕事のやり方が間違ってなかったという自信を持てたことは大きい経験でした。業務内容についてはまだ言語化できていない部分がたくさんあるので、来年はそこに少し時間を割きたいという気持ち。

今年の体外発表はその1回のみ、ブログも0本なのでアウトプットはかなり少なかったです。来年はもう少し増やすつもり。

インプット

  • 本を読む量を意識的に増やした結果50冊弱くらい読めた。小説4割、一般書4割、技術書2割くらいの割合
  • CourseraのMachine Learningのコースを修了した。次のコースを検討中

www.coursera.org

  • 会計まわりの勉強を始めた

その他雑多なこと

  • 一回胃腸炎で39℃の熱が出たりしたが、風邪もほとんどひかず全体的に健康に過ごせた
  • 体重がmax85kgまで来てしまったのでトレーニング&ダイエット始めた。今は80kg. 来年中頃に72kgまで落としたい
  • クロスバイク買った。楽しい。今は寒いのでお休み中。暖かくなってきて自転車熱が冷めてなかったらロードバイク買いたい

www.colnago.co.jp

  • ペーパードライバー講習に通った。10コマ契約したけど4コマくらいで十分だった
  • 運転できるようになったのでタイムズのカーシェアを契約した。QoLが格段に上がった。

share.timescar.jp

最後に

来年も健康を維持しながら生きていきます。

notionでプライベートな日記をつけ始めた

1ヶ月ほど前、このツイートを見てnotionを使い始めた。

自分のメモやプライベートなTODOを溜め込んでいる状態でしばらく使っていた。かなり便利に使えることがわかってきたので最近は日記をnotionに書くようにしている。

もともとは大学時代、物理的な日記帳に

  • その日起こったこと
  • それに対して何を思ったか

などを書いていた。就職してからその習慣が薄れてしまっていたが、先日偶然学生時代の日記を発掘して読み直して2828する機会があったので、またつけはじめようと思った。ただ、流石に物理的な日記に今更手を出すのもなー、と思っていたのでnotionに日記を書いてみることにした。

notionにはページ内にinlineでカレンダーを挿入する機能があり、そこにリンクでページを挿入できるので、ひとまずその形で今週から使い始めた。今の所いい感じで使えている。モバイルから編集もできるので移動時間とかにパッと書き込めるのがよい。

こういう日々の積み重ねが数年後に自分を2828させてくれると思うと、結構日記書くのが楽しみだったりする。この楽しみをしばらく継続させていければいいな。

と同時に、パブリックなアウトプットも増やしていかなければいけないんだけど。

MySQLテーブルのデータ件数はinformation_schema.tablesから取得できる

前提

やりたいこと

MySQL上のテーブルに COUNT(*) することなく、テーブルの行数を知りたい。

解決法

information_schema.tables テーブルから、テーブルの名前やデータ件数などのメタデータが取得可能。

mysql> desc information_schema.tables;
+-----------------+---------------------+------+-----+---------+-------+
| Field           | Type                | Null | Key | Default | Extra |
+-----------------+---------------------+------+-----+---------+-------+
| TABLE_CATALOG   | varchar(512)        | NO   |     |         |       |
| TABLE_SCHEMA    | varchar(64)         | NO   |     |         |       |
| TABLE_NAME      | varchar(64)         | NO   |     |         |       |
| TABLE_TYPE      | varchar(64)         | NO   |     |         |       |
| ENGINE          | varchar(64)         | YES  |     | NULL    |       |
| VERSION         | bigint(21) unsigned | YES  |     | NULL    |       |
| ROW_FORMAT      | varchar(10)         | YES  |     | NULL    |       |
| TABLE_ROWS      | bigint(21) unsigned | YES  |     | NULL    |       |
| AVG_ROW_LENGTH  | bigint(21) unsigned | YES  |     | NULL    |       |
| DATA_LENGTH     | bigint(21) unsigned | YES  |     | NULL    |       |
| MAX_DATA_LENGTH | bigint(21) unsigned | YES  |     | NULL    |       |
| INDEX_LENGTH    | bigint(21) unsigned | YES  |     | NULL    |       |
| DATA_FREE       | bigint(21) unsigned | YES  |     | NULL    |       |
| AUTO_INCREMENT  | bigint(21) unsigned | YES  |     | NULL    |       |
| CREATE_TIME     | datetime            | YES  |     | NULL    |       |
| UPDATE_TIME     | datetime            | YES  |     | NULL    |       |
| CHECK_TIME      | datetime            | YES  |     | NULL    |       |
| TABLE_COLLATION | varchar(32)         | YES  |     | NULL    |       |
| CHECKSUM        | bigint(21) unsigned | YES  |     | NULL    |       |
| CREATE_OPTIONS  | varchar(255)        | YES  |     | NULL    |       |
| TABLE_COMMENT   | varchar(2048)       | NO   |     |         |       |
+-----------------+---------------------+------+-----+---------+-------+
21 rows in set (0.00 sec)

mysql> select * from tables where table_schema = 'information_schema' and table_name = 'tables';
+---------------+--------------------+------------+-------------+--------+---------+------------+------------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+-------------+------------+-----------------+----------+----------------+---------------+
| TABLE_CATALOG | TABLE_SCHEMA       | TABLE_NAME | TABLE_TYPE  | ENGINE | VERSION | ROW_FORMAT | TABLE_ROWS | AVG_ROW_LENGTH | DATA_LENGTH | MAX_DATA_LENGTH | INDEX_LENGTH | DATA_FREE | AUTO_INCREMENT | CREATE_TIME         | UPDATE_TIME | CHECK_TIME | TABLE_COLLATION | CHECKSUM | CREATE_OPTIONS | TABLE_COMMENT |
+---------------+--------------------+------------+-------------+--------+---------+------------+------------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+-------------+------------+-----------------+----------+----------------+---------------+
| def           | information_schema | TABLES     | SYSTEM VIEW | MEMORY |      10 | Fixed      |       NULL |           9441 |           0 |        16757775 |            0 |         0 |           NULL | 2017-07-09 23:15:45 | NULL        | NULL       | utf8_general_ci |     NULL | max_rows=1777  |               |
+---------------+--------------------+------------+-------------+--------+---------+------------+------------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+-------------+------------+-----------------+----------+----------------+---------------+
1 row in set (0.01 sec)

table_row カラムにデータ件数が格納されている。このテーブルを利用すれば、任意のテーブルの行数を COUNT(*) することなく取得が可能。

mysql> select * from tables where table_schema = 'foo_db' and table_name = 'bar_table';
+---------------+--------------+------------+------------+--------+---------+------------+------------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+---------------------+------------+-----------------+----------+----------------+---------------+
| TABLE_CATALOG | TABLE_SCHEMA | TABLE_NAME | TABLE_TYPE | ENGINE | VERSION | ROW_FORMAT | TABLE_ROWS | AVG_ROW_LENGTH | DATA_LENGTH | MAX_DATA_LENGTH | INDEX_LENGTH | DATA_FREE | AUTO_INCREMENT | CREATE_TIME         | UPDATE_TIME         | CHECK_TIME | TABLE_COLLATION | CHECKSUM | CREATE_OPTIONS | TABLE_COMMENT |
+---------------+--------------+------------+------------+--------+---------+------------+------------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+---------------------+------------+-----------------+----------+----------------+---------------+
| def           | foo_db        | bar_table   | BASE TABLE | InnoDB |      10 | Dynamic    |      19303 |           1336 |    25804800 |               0 |      4767744 |   4194304 |           NULL | 2017-06-23 00:25:12 | 2017-07-03 11:36:54 | NULL       | utf8mb4_bin     |     NULL |                |               |
+---------------+--------------+------------+------------+--------+---------+------------+------------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+---------------------+------------+-----------------+----------+----------------+---------------+
1 row in set (0.00 sec)

このテーブルを利用することで、 データ件数が一定数以上のテーブルを抽出する みたいなこともできる。ただし、このテーブルには mysql スキーマinformation_schema スキーマなどの管理データやメタデータスキーマも含まれるのでそれを必ず除外する必要がある。対象のスキーマを条件に入れて検索すること。

SELECT table_name, table_rows
FROM information_schema.tables
WHERE table_schema in ('foo_db', 'bar_db')
AND table_rows > 1000;

information_schema 以下には他にも面白そうなテーブルがたくさんあるのでもうちょっと深く掘りたい。

(2017/07/11 13:13 追記)コメント欄で id:n-3104さんから指摘頂きましたが、 table_rows で取得できる行数は概算の値で、その瞬間での正確な値ではありません。概算量が取得できれば問題ないような要件であれば活用できますが、正確な量が知りたい場合は各TABLEに COUNT(*) をかける必要があります。 また、 ANALYZE TABLE を実行することで、テーブル単位での同期をかけることが可能です。

(追記ここまで)

参考

私は何に対してお金をもらっているのか、という話

受託システム開発においては、「人月」という単位でお金の計算をされることが(少なくとも私の観測範囲下では)多いと思う つまり、「人」がどれだけ動くかに対しての報酬を要求するというもの。 このスキームのもとで動く人は、つまり「時間」からお給料をいただいている。

一方、「人」ではなく、「人がつくりだす価値」に対してお金をもらうケースもある。 何かしらのサービスプロバイダはその分類に入るだろう。 そのスキームのもとでは、動いた時間とは無関係に、人ないし組織が提供する「価値」に対して報酬が与えられる。

時間は有限である。だから、時間に対してもらえるお金も有限である。 だが、自分が作り出すことができる価値は有限ではない(と、信じている)。 であれば、その価値を生み出すことにフォーカスしていくのが自然な流れかなと思った。

とはいえ自分が時間ではなく価値を提供できているのか、わからない。

でもこの先の人生において、時間を自分の売り物にしていくには時間が足りなさすぎる、というのがここ数ヶ月の感想。 だからこそ自分は、時間ではなく価値を売り物にする人間になりたい。

自分は何に対してお金をもらっているんだろうか。 ということに一度向き合ったほうがいいな、と思いました、まる

Array#newする時の初期値は同一オブジェクトになる

本日のRubyに関する学び。

[32] pry(main)> arr = Array.new(3, Array.new(4,0))
[
    [0] [
        [0] 0,
        [1] 0,
        [2] 0,
        [3] 0
    ],
    [1] [
        [0] 0,
        [1] 0,
        [2] 0,
        [3] 0
    ],
    [2] [
        [0] 0,
        [1] 0,
        [2] 0,
        [3] 0
    ]
]
[33] pry(main)> arr[0][0] = 1
1
[34] pry(main)> arr
[
    [0] [
        [0] 1, #<= ここが1になるが、
        [1] 0,
        [2] 0,
        [3] 0
    ],
    [1] [
        [0] 1, #<= ここと
        [1] 0,
        [2] 0,
        [3] 0
    ],
    [2] [
        [0] 1, #<= ここも1になる。
        [1] 0,
        [2] 0,
        [3] 0
    ]
]

Array.newする時に第二引数で配列の要素を埋める初期値を指定することができるが、ここで指定したobjectは全て同一のオブジェクトになる。今回の例では、Array.newされた単一のArrayが3つの要素に埋められる。そのため、一つの要素を変更するとその他の要素にも変更が及んでしまう。

[35] pry(main)> arr[0].object_id
70212079356840
[36] pry(main)> arr[1].object_id
70212079356840
[37] pry(main)> arr[0].object_id.eql?(arr[1].object_id)
true

訳あって多次元配列を作っていたらハマったので。

Array#mapで多次元配列を扱う時、複数個のブロック引数で値をとれる

本日のRubyに関する学び。

a = [1,2,3]

a.map do |element|
  element.class #=> Fixnum,Fixnum,Fixnum
end

a.map do |first,second|
  second #=> nil,nil,nil
end
  
b = [[1,2],[3,4],[5,6]]

b.map do |element|
  element.class #=> Array
end

b.map do |first,second|
  second #=> 2,4,6
end

ドキュメントにも可変長引数に関する言及が無かったので最初よく分からなかったが、How does Array.map work for 2D arrays? - Ruby Forumを読んでいたら仕組みについては少し腹落ちした感じがある。

とはいえまだ人に説明できるほど理解できたわけではないので後日もう一回読む。

AWS re:Invent 2014感想文

11/10〜11/16の期間、ラスベガスで開催されたAWSの大規模カンファレンス「AWS re:Invent 2014」に参加してきた。1万人以上が参加する超大規模なカンファレンスに、会社を代表する形で4名で参加させてもらった。 セッションやKeynoteの内容については会社のブログで腐るほど書いたので*1、もっと個人的な感想とかをメモっておく。

セッション全体

昨年のre:InventではKinesisとかWorkspacesとか、それまでのAWSの領域とは少し毛色の違うサービスが追加されたけれど、今年の新サービスはどれも、「ああ、それ欲しかったよね」とか「なるほど。。」と唸る機能が多かった印象。Keynoteと新機能紹介のセッションを聞いた感じ、KMSは既にPublicになっているし、機能としてもかなりイケてるんじゃないかと思った。ただセキュリティ系はあまり詳しくないので実際に使ってみないとなんとも言えない。これから試してみる。

通常セッションではNetflixとかDropboxみたいにコアに使い倒している企業の使い方を聞けたのが素晴らしかった。自分で参加したり、資料を読んだりした中で特に素晴らしいと感じたのは以下のセッション。これからも見つけ次第追加していく。

その他

英語に関して

セッションの内容とか展示ブースでの会話は7〜8割聞き取れて、ブースで説明されたプロダクトに関しての質問とかもそれなりにできるんだけど、店の店員とか他人に声をかけられた時に反応できなくて困った。英語は大丈夫だろうとかなり高を括って参加していたので結構ショックではある。レアジョブやろうかな、と本気で思案中。

アメリカに関して

ラスベガスのホテルという、なんというか非日常な領域に滞在していたので、あまりアメリカでの生活に触れられた感じはしていないけど、アメリカの文化の一端には触れることが出来たかな、という感じ。イギリスに滞在していたときの間隔と比較すると、やはりアメリカはイギリスよりは文化的に日本に近い印象を受けた。当然本気で現地で生活するor仕事する、となると全く別次元の話になることは認識しているけど。次はもう少し一般の生活に触れられるところに行きたい。できれば仕事で。

re:Inventというイベントに関して

とにかく何から何まで規模が違いすぎて焦った。Keynote会場の集客と熱気、各セッションの内容の濃さ、re:Playの桁外れのパーティー感、などなど。本当に参加できてよかったと思う。自分自身の価値観に影響を与えられた気がする。

まとめ

  • 英語はがんばる
  • 新機能は使い倒す
  • 来年も行きたい
  • 今年行っていない人は来年行くといいと思います
  • 眠い

*1:まだ書いてるよ!