新卒入社したSESの会社を退職しました
新卒で入社して3年半ほど務めました。9月26日が最終出社日でした。 前職でどのようなことを経験してきたか書いてみようと思います。
前職について
一応正社員契約でしたが、SESと呼ばれるものでお客様先に派遣されて勤務します。いわゆる客先常駐というやつです。メリットは短期間で複数の現場に派遣されるので、転職することなく複数の業界/現場で働くことができることだと思います。
前職で担当した仕事&仕事に関連して学んだこと
Salesforce
salesforceは簡単に言ってしまえばインフラとかミドルウェアの構築が一切不要なPaaSのことです。
簡単な顧客管理機能等がバインドされています。画面をクリックするだけで簡単なアプリケーションを作成することができます。
また
を組み合わせることで柔軟なアプリケーションの構築が可能です。割と少ない工数で形になるものが出来上がるので、前職のような小さい会社と相性がいいのかなという印象です。
Salesforce社は自社でprogateのようなSalesforceを学べる教育サイトTraiheadを持っており、これの出来が非常に良いです。
COBOL,Javaのマイグレーション
COBOLで書かれたシステムをJavaで書き直すという経験が出来ました。業務分析などはせずに基本的にCOBOLのソースを一行単位で一致するJavaに置き換えます。一応証拠としてJavaのソースに対応するCOBOLをコメントアウトして添えていました。こんな感じです。
//PRODUCT-NO PIC 9(8). 👈移行後のJavaのコードに対応するCOBOLのコードをコメントアウトして残しておく Integer productNo; //👈 移行後のJavaのコード
デバッグスキル
諸事情により納期前のどうしてもバグが取れない5万行程度の機能のバグ取りの担当になりました。 ほぼ新人の自分が完成できるか不安しかありませんでした。
とにかく自分が知っている道具は全て駆使しました。Eclipseの条件付きブレークポイントとか、Watch式とか。 結局、EclEmmaというプラグインを導入してメソッドごとにカバレッジを取りながら、 微妙テストデータを変えながら調査を行ったのが一番効きました。正しい値を出す/出さない時でカバレッジが変わっているメソッドに徹底的にブレイクポイントとWatch式を貼ってデバッグしました。
バグは結局全て見つかりました。
ryokin12[1][2]
こういう複雑な変数名や[]
内のindex- if分の大小条件
が微妙に違ったりしているものでした。 見つかった時は創意工夫して結果が出たことが非常に嬉しかったし、納期にも間に合うことができました。でも汎用機からオープン系へのマイグレーションは社内にノウハウがあるような巨大なSIerでないとしんどいと思います。
テスト
テストをすることが多かったため 在籍中にテストに関する本を5冊読みました
- 作者: 高橋寿一
- 出版社/メーカー: 翔泳社
- 発売日: 2013/12/10
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (7件) を見る
- 作者: Kent Beck,和田卓人
- 出版社/メーカー: オーム社
- 発売日: 2017/10/14
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (1件) を見る
- 作者: セムケイナー,ジャームズバック,ブレットペティコード
- 出版社/メーカー: 日経BP社
- 発売日: 2013/11/20
- メディア: Kindle版
- この商品を含むブログ (5件) を見る
レガシーコード改善ガイド (Object Oriented SELECTION)
- 作者: マイケル・C・フェザーズ,ウルシステムズ株式会社,平澤章,越智典子,稲葉信之,田村友彦,小堀真義
- 出版社/メーカー: 翔泳社
- 発売日: 2009/07/14
- メディア: 大型本
- 購入: 45人 クリック: 673回
- この商品を含むブログ (157件) を見る
- 作者: リー・コープランド,宗雅彦
- 出版社/メーカー: 日経BP
- 発売日: 2005/11/03
- メディア: 単行本
- 購入: 24人 クリック: 539回
- この商品を含むブログ (51件) を見る
※5冊目は今読んでいます
テストは製品の品質を担保する重要なプロセスだと思っています。 そこが軽視されていたり、いい加減だったりするのよくありません。 今ではテストは知的興奮が大いにある物作りのエキサイティングな分野の一つだと思っています。
テストや品質保証を専門にキャリアを築いている人も社外で何度かあいました。 そういう人の生き方は尊敬しているし、決してテスト=雑用では無いと思っています
偉そうなことを行っているが以下は自分もよくわかっていません
- 複雑な平行/並列処理が絡むテスト
- 大規模なシステムの負荷テスト
- テストの自動化のためのテクニック(特にフロントエンド周り)
フロントエンド周りの知識
フロントエンド周りの技術は進歩というか変化が特に激しく、 サーバーサイド側の人間が片手間で追従できるものでは無いと思っています。 だからフロントエンド周りのスキルは時間をかけて基礎からじっくり勉強するつもりはありませんでしたが、 どうしても作っているものに納得が行かなかったため何冊か本を読んで勉強しました。
- 作者: 高橋朋代,森智佳子
- 出版社/メーカー: SBクリエイティブ
- 発売日: 2013/12/14
- メディア: 単行本
- この商品を含むブログ (11件) を見る
改訂新版JavaScript本格入門 ?モダンスタイルによる基礎から現場での応用まで
- 作者: 山田祥寛
- 出版社/メーカー: 技術評論社
- 発売日: 2016/09/30
- メディア: Kindle版
- この商品を含むブログを見る
JavaScriptパターン ―優れたアプリケーションのための作法
- 作者: Stoyan Stefanov,豊福剛
- 出版社/メーカー: オライリージャパン
- 発売日: 2011/02/16
- メディア: 大型本
- 購入: 22人 クリック: 907回
- この商品を含むブログ (76件) を見る
※3冊目は見事に途中で挫折していますね
フロントエンドエンジニアとして世間一般で通用する自信はありませんが、 フロントエンド技術を利用しているチームの成果物の改善にはかなり貢献できたと思います。
フロントエンド技術(UI/UX)の本質的な難しさは,非技術者のもっとも関心が高くなる部分という点だと思います。 現場によってはカジュアルな仕様変更などが多数発生します。
ここをしっかり戦い抜いていくには技術以外にも人間工学とか、心理学とかもしっかり抑えて 「なぜそのデザインがBestなのか」を説得できる能力が必要だと思いました。
Javaとかオブジェクト指向とか
大学時代はほとんどJavaを触っていませんでした。趣味でAndroidアプリの入門書を一通りやったり、大学で1コマそういう授業があっただけでした。
Javaは動かし始めるまでに覚えないといけない概念が多いわりに、それが駆使できるのはもっと経験が必要なので、覚えた概念の恩恵みたいなものはイマイチわからなかった。 結局最初はC言語によくわからないキーワードが大量に引っ付いたプログラムみたいな印象を受けました。
で就職してからはこれを使わなくてはならないと思って、Javaを本格的に学んだ。
なぜ、あなたはJavaでオブジェクト指向開発ができないのか―Javaの壁を克服する実践トレーニング
- 作者: 小森裕介,アクロクエストテクノロジー株式会社
- 出版社/メーカー: 技術評論社
- 発売日: 2004/12/01
- メディア: 単行本
- 購入: 10人 クリック: 217回
- この商品を含むブログ (50件) を見る
- 作者: 平澤章
- 出版社/メーカー: 日経BP
- 発売日: 2011/04/07
- メディア: 単行本
- 購入: 6人 クリック: 92回
- この商品を含むブログ (20件) を見る
- 作者: Joshua Bloch,柴田芳樹
- 出版社/メーカー: 丸善出版
- 発売日: 2018/10/30
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (2件) を見る
Javaは動かし始めるまでに覚えないといけない概念が多いわりに、それが駆使できるのはもっと経験が必要なので、覚えた概念の恩恵みたいなものはイマイチわからなかった。
大学時代分からなかったこの箇所がわかるような気がしてきた。 だから必死で勉強しました。特に後者の2冊はとても勉強になった。 Javaのプロジェクトには数週間しか関われていないけど*2、Java及びその関連技術(JVM言語等)を自分の強みにしていきたいという思いがあります。
正規表現
事務作業が8割くらいの時期があり、雑務にひたすら正規表現を使って進めることで退屈をしのいでいました。
きちんと本で勉強して覚えたわけではないけど、1ヶ月程度毎日ググりながら正規表現を書いていたので、機械的に行えば良いだけのテキスト変換、置換などは、加工対象の文字を大体見ただけでどういう正規表現を書けば良いか思いつくし、ほとんど空で書けるようになりました。
正規表現完全に理解した!と思って調子に乗ってネットにいい加減なこと書きまくって、ある日rubyの正規表現エンジン(Onigmo)を作ってる人から訂正コメントが飛んできて、自分は何も理解できてない、と自信を失ったりしたこともありました。
位置指定子っていう概念が微妙に理解できていないこと以外はだいたい実践的な部分では困らなくなった。あと計算量とかパフォーマンスの理解が不十分。
大学のころ、正規言語とかオートマトンの授業を取っていたので、この辺はきちんと勉強したいですね。
SQL&RDBMS
開発がやりたかったけど、結局規模の大きい保守案件に配属になった。データはたくさんあったので*4SQLとRDBを勉強すると自分にも会社にも+になるだろうなと思い、勉強し始めた。
ある日バグの影響範囲を調査するため、再帰クエリが適応できそうな調査案件があった。 他のメンバーはお手上げだったが、急いで技術調査をして調査のクエリを作った。その時復習した内容は以下の記事にまとめてあります
こういう風にやればできますよと提案して、結局自分が担当になってそのデータを調査、修正するクエリを書いた。 あの時は純粋に学んできたことが活きた数少ない瞬間だった。自分にも会社にも+になったと思う。
Excel VBAや自作スクリプトによる調査の効率化
大規模なシステムだったので、目grepが厳しいのでExcel VBAやJavaScriptを使って効率的に調査をするツールを作成しました
VB.NETのクラスを調査するファイルを作っていて、
https://teratail.com/questions/118863
vbのこんな仕様に悩んだりしていました。
プログラムの解析を正規表現でゴリゴリ書いていましたが限界を感じました
http://leoclock.blogspot.com/2009/01/blog-post_27.html
仕事関係ないけどこの経験から少し言語処理系とかに興味を持つようになりました
セキュリティ
詳しくは書きませんが、システムのセキュリティ強化のため個人的に勉強していました。
体系的に学ぶ 安全なWebアプリケーションの作り方 第2版[リフロー版] 脆弱性が生まれる原理と対策の実践
- 作者: 徳丸浩
- 出版社/メーカー: SBクリエイティブ
- 発売日: 2018/09/20
- メディア: Kindle版
- この商品を含むブログを見る
「プロになるためのWeb技術入門」 ――なぜ、あなたはWebシステムを開発できないのか
- 作者: 小森裕介
- 出版社/メーカー: 技術評論社
- 発売日: 2010/04/10
- メディア: 大型本
- 購入: 57人 クリック: 1,242回
- この商品を含むブログ (35件) を見る
色々指摘することができましたが、進捗にはマイナスでしかなかったので、迷惑だったかなと思います。
会社へのSlack導入
脱メールでのコミュニケーションを目標に、上司への提案でSlackをチームで採用していただきました。チーム、部という順番で広がっていったのでおそらく、退職後しばらく経てば全社的に使っていると思います。
これから中小企業で導入して見たいけど、使い方が良く分からない。。。という人は最近は技術コミュニティでもSlackを積極的に使っているので、 そちらに参加して慣れながら活用方法を学んでいけば良いと思います。
私ができなかったこと、足りなかったこと
自社/協力会社の有志で勉強会
どうしても業務で経験できることには限界があるので、エンジニアには業務以外での技術研鑽が必要だと思います。 SESというのは客先の稼働時間が大事なので基本的に就業時間内に勉強はできませんが、 もっと仕事で使っている技術やフレームワークについて、特に新人を含めた勉強会などができたらよかったと今になって思います。
ちなみに仲良くなったパートナー会社の社員さんには技術書を貸したり、JavaScriptの基本を教えたりしていた。
本の紹介を依頼され、他社の新人にリーダブルコードを貸した。チョイスは仕事中メソッド名や見やすいSQLのインデントに何度も悩み、他の開発者に相談している姿を何度も見たため。きっと役に立つと思う。
— yuYabu@転職中 (@yuyabu2) March 2, 2018
コミュニケーション
私はお酒が飲めないこともあって、非常に人付き合いが悪かった。別に飲み会を欠席したことで非難されるようなことは1度くらいしかなかったけど、 そういう所で信頼関係が結べていなかった所でスムーズに物事が運ばなかった面はあったと思います。
またあまり失礼とか気にせず思ったことを口にするタイプだったので、色々勉強して見ました。
まだまだ未熟者ですが日々修行中です
今後
働く前は開発こそ至高みたいな考え方があったけど、自宅学習でそれなりにスキルを高めて、問題解決ができれば保守/調査/テストも面白いと思いました。 でも開発をあまりやらせてもらえなかったので開発をしたい思いが強いです
今後は以下の業務に関わってみたいです
最後になりましたが、前職では社長、前社長、前前社長をはじめ、様々な方々のお世話になりました。 本当にありがとうございました。
Java読書会「現場で役立つシステム設計の原則」を読む会 第2回に参加
遅れて午後から参加しました。今回は、書かれていることは確かに理想だけど...という切り口の議論が多かったように思います
現場で役立つシステム設計の原則 〜変更を楽で安全にするオブジェクト指向の実践技法
- 作者: 増田亨
- 出版社/メーカー: 技術評論社
- 発売日: 2017/07/05
- メディア: Kindle版
- この商品を含むブログ (4件) を見る
かんしんごと vs かんしんじ?
(業務の) 関心事 ← 「かんしんじ」vs.「かんしんごと」で意見が割れている。自分は「かんしんじ」派かなぁ #javareading
— YutakaKato.jar (@kagaorange) September 29, 2018
#javareading
— yuYabu@転職中 (@yuyabu2) 2018年9月29日
関心事=かんしんごと?かんしんじ?どっちの読みが正しい?という話になった。昔みた増田さんが話しているビデオだと「ごと」で読んでたような?
増田さんの発表を聞いた人のブログにも「関心ごと」と書かれているので多分「ごと」が適切だと思うのですがhttps://t.co/kn8w21bhpj
YutakaKatoさんと漢字の読みで張り合っています
私は著者が講演で「かんしんごと」と発音しているビデオ(1:28:2~)に影響を受け、これにつられて「かんしんごと」で通しています
なぜ「関心事」だけ「じ」と読むのでしょうか?
「心配事」はいわば和語扱い、「関心事」は漢語扱いだからです。
日本語の読み方的には「かんしんじ」が正しいようです😇。DDD界隈読みということもありえるのでしょうか。
まぁ漢字の読み方とかにこだわっているわけではありませんが、この本やたらと「関心事」という単語が出てくるので、どうしても気になってしまうのです。
なんと252回も!出てきますw
とりあえずDRYみたいなのは有害
- 共通しているからという理由でまとめてはいけない。ドメインの観点から検討して、本当に共通か? を意識して共通化する必要がある。
- 共通化というのは結果にすぎない。
- とにかくDRY原則!というのが有害
- 日時系のAPIは日付概念はものすごく抽象化されているから便利に使える
- とりあえずなんとなく共通処理をまとめました、だと誰も使わない
https://qiita.com/tag1216/items/91a471b33f383981bfaa
- ドメインを考えるのはすごく大変。重複クラスをまとめるだけなら脳みそを使わない。
Accountパターンの出どころは?
関心事のパターン | 業務ロジックの内容 |
---|---|
口座(Account)パターン | 現在の値(現在高)を表現し、妥当性を管理する |
期日(DueDate)パターン | 約束の期日と判断を表現する |
方針(Policy)パターン | 様々なルールが複合する、複雑な業務ロジックを表現する |
状態(State)パターン | 状態と、状態遷移のできる/できないを表現する |
業務ルールを記述するドメインオブジェクトの基本パターンより抜粋
ちょっと議論の内容は失念したが、こういうプログラミングのプラクティスは
エンタープライズ アプリケーションアーキテクチャパターン (Object Oriented SELECTION)
- 作者: マーチン・ファウラー,長瀬嘉秀,株式会社テクノロジックアート
- 出版社/メーカー: 翔泳社
- 発売日: 2005/04/21
- メディア: 大型本
- 購入: 10人 クリック: 635回
- この商品を含むブログ (143件) を見る
アナリシスパターン―再利用可能なオブジェクトモデル (Object Technology Series)
- 作者: マーチンファウラー,Martin Fowler,堀内一,友野晶夫,児玉公信,大脇文雄
- 出版社/メーカー: ピアソンエデュケーション
- 発売日: 2002/04
- メディア: 単行本
- 購入: 7人 クリック: 89回
- この商品を含むブログ (70件) を見る
エリック・エヴァンスのドメイン駆動設計 (IT Architects’Archive ソフトウェア開発の実践)
- 作者: エリック・エヴァンス,今関剛,和智右桂,牧野祐子
- 出版社/メーカー: 翔泳社
- 発売日: 2011/04/09
- メディア: 大型本
- 購入: 19人 クリック: 1,360回
- この商品を含むブログ (131件) を見る
などが元になっていたりするらしい。 読書家な人が集まっているので「このパターンは一般的なやつ、このパターンはXXに乗ってるやつだね」という流れになったが、Accountパターンは何が元になっているか?という結論が出なかった。 エリックエバンスの本は手元にあったので一応中を調べてみたが、それらしいものはなかった
- PoEAAの訳はひどい
- とても読めたものではないので捨てた
粒度の小さいクラスを大量に作ることの是非
本書では単位や属性のクラスをかなり細かく作成していくが、クラス数が増えるほど依存関係が増えたり複雑になるので、とりあえずクラスを小さくすれば良いというものではない。
個人的に大事なことは責務が混ざらない程度に小さくすることだと思う
他技術的なトピックなど
適当に議論中に出たトピックをまとめます
for文でコレクションを確認しているコードはStream APIのAnyMatchなどを使うべき
JavaのStringクラスの方がクラス設計としては良いが、結果的にRubyが文字列をただのバイト列として扱っているやり方のほうが結果的に成功している
- JavaがStringクラスに採用している設計パターンが結果的に良くなかったという趣旨の話があった
JSR-305
@NotNull
などのアノテーションの標準化
Kotlin最高
- Springの開発スピードが早い(Kotlinの開発がついていけてないらしい)
次回は「小さく分けたサービスを組み立てる」から
CC本読み会第12回
Concurrency Control and Recovery in Database Systemsを読む勉強会です。
内容としてはロックのパフォーマンスに関してです。今回のポイントは競合の種類(Resource/Data)と競合を回避する手段(abort/block)がメインだと思います よくわからない箇所があったので自宅で復習しました。
今回はp87から
- 3.12 LOCKING PERFORMANCE
- Resource and Data Contention
- Thrashing
- Blocking and Restarts
- Predeclaration
- A Bound on Workload
- MPL, Transaction Length, and Granularity
- Read Locks and Nonuniform Access
を読みました。次回は「3.13 TREE LOCKING」からになります。
Concurrency Control and Recovery in Database Systems
- 作者: Philip A. Bernstein,Vassos Hadzilacos,Nathan Goodman
- 出版社/メーカー: Addison-Wesley
- 発売日: 1987/02/01
- メディア: ハードカバー
- この商品を含むブログを見る
目次です
競合(Contention)に関して
- 競合には2種類ある。リソース競合とデータ競合。
- リソース競合(Resouce Contation):メモリやIO待ちなどのシステム的な部分
- データ競合(Data Contation):ロックに関連する競合
- 多かれ少なかれ多くのシステムは(物理上のスペックの上限があるので)リソース競合が発生しうる。
- リソース競合以外の競合としてデータ競合が定義できることは発展的な議論をするために便利な概念となる。
- データ競合はリソース競合を緩和する可能性がある
Resource contention also hurts a pure restart policy more than a blocking policy. With the latter, some transactions are blocked in lock queues, so fewer transactions compete for resources. (Thus, data contention alleviates resource contention for a blocking policy.)
- データ競合が起きてできることが少なくなると、リソースの利用率が下がる。
競合に伴うパフォーマンス低下(Thrashing)について
- リソース競合,データ競合それぞれに応じてThrashingが発生する恐れがある
- DC Thrashing:ロックの取り合いによって生じるパフォーマンス劣化のこと(デッドロック含む)
- RC Thrashing:スタベーション,またはlive lockのこと
- DCスラッシングに関してはDBMSのリソースが無限にあっても発生する恐れがある
- DC Thrashing pointを超えてからトランザクションを増やすと、blockされていないトランザクションの数が減少する
競合の解決方法
競合(Data Contation)の解決方法は2種類ある
- blocking戦略:ロックが解放されるまで待たせるロックキューを作る(waitさせる)
- restart戦略:専有しようとしたリソースがすでにロックされていた場合、トランザクションをabortして最初からやり直す
一般的なRDBMSの実装状況
- blocking/restartは設定で選べないのか?
- 中身の処理内容が全く違うので設定で切り替えるような問題ではない
blockingとrestartsのパフォーマンスの比較
- restartする方が一見コストが高いように見える
- 再起動のコストを払う必要になるため
- 中断した箇所までのトランザクション処理の成果は捨てられるため
- が実際にはblocking戦略の方が早く性能劣化(Thrashing)を引き起こす
- blockingがrestartsより良いという理屈は次の状況が両方発生する場合に
- restartに時間がかかりすぎる → 実装によって回避可能
- リソース競合が頻繁に怒る → CPU数を増やすことによって回避可能
restartの方がblockingより応答時間は増える
- restert時にロック解放する必要があるため*1
ロックの取り合いをさせるくらいならアボートさせる方が良いというのが最近のDB界隈のトレンド
トランザクションは本来APエンジニアに見せるべきではない
- 本来ならAPエンジニアにはcheckpointを設定させるだけにするべき
ブロックは利己的
リスタートは自己犠牲的
abortは処理が重そうだけどlockの方が軽いのではというのが一般的だが、実態はabortさせてredoする方がパフォーマンスが良い。
2PLの検討(Basic 2PL,Conservative 2PL)
Basic 2PLとConservative 2PLについて地球で一番わかりやすい解説はこちら
※以後Basic 2PLをB2PL,Conservative 2PLをC2PLと略します
- 理屈上はB2PLの方がC2PLよりロックを保持している時間が短い
- 一見B2PLの方がパフォーマンス上メリットがありそうである
- ただしこれはデータ競合の発生が少ない場合のみ。
- データ競合の発生が激しくなるにつれC2PLの方がロックを保持している時間が短くなる
この節p91の「Predeclaration」ですがなぜデータ競合が多いとC2PLが勝るのか、 根拠がよくわかりませんでした。
結論としてはC2PLを導入することによって - デッドロック回避 - DCスラッシングの阻止(軽減) のメリットある。(後者の方が期待度が高い)
性能限界 ~DC Thrashing ギリギリまでパフォーマンスをあげる~
リソースが無限と考えても、トランザクションを増やしたり、並列化するとスループットは上がるが、どこかで下がるポイント(DC Thrashing)がある。
DC-thrashing thus defines an operating region the combination of parameters that affect the performance.
実はこれは計算で算出可能
- N:MPL(multiprogramming level)多分トランザクション数
- k:一つのtransactionが要求する平均lock数
- D:データ資源
の時DC Waolkoad
だから性能限界は
となる。が、これは
- DBアクセスが一様的である前提
- ピークとかない。増減しない平均的な接続が常に発生するイメージ
- リソース競合を考慮していない
なのでかなり楽観的な数値である。 あくまで1.5というのはこの規模の数字である、という参考を示しているにすぎない。
MPLについて
- MPL(並列化するプロセス数)は1.5D/k2以上あげるべきではない。
- N(MPL)をあげるとデッドロックが発生する率も上がる
- restartのコストが高い場合はさらにNを下げる必要がある
Long Transactionについて
以下の事象はスループットを下げる要因となる
そもそもトランザクションよりもロックが増えることによる影響が大きいので トランザクションを分割することでworkloadをあげることができる
例えば
前述の式
に当てはめると
となり、これは分解前のより倍よくなっている。
Granularity(粒度)について
Granularityの定義はchapter1のp2に書いてある
The size of the data contained in a data item is called the granularity of the data item.
- 小さいD(荒い granularity)は大きな範囲にロックがかかる
- 大きいD(細かい granularity)は小さな範囲にロックがかかる
Granularityが性能に及ぼす要因は3つある
- 1.ロックオーバーヘッド
- granularityが細かいほどロックが必要=オーバーヘッドが増える
- 2.データ競合
- granularityが荒いほどデータ競合が起こる可能性がある
- ただし、granularityが細かければ良いという訳ではない
- 一般的にgranularityが細いほどロックが増える傾向にある
- ロックが増えるともちろんロックの衝突(Data contation)も起こりやすくなる
- 3.リソース競合
- 前述したが、データ競合はリソース競合を改善する可能性がある
- ranularityが荒いとリソース競合が起きにくい。
- ranularityが細かいとリソース競合が起きやすい
- 前述したが、データ競合はリソース競合を改善する可能性がある
上記の3要因を踏まえるとGranularityによるスループットの変化は以下のグラフのようになる
ただしこのグラフのようなスループット増減を必ずとるわけではない
Read Lock
- 今まではWrite Lockを前提に考えてきたが、lockの何割かがread lockと考えるとパフォーマンスは工場する
- アクセスの偏り
- アクセスの偏りが発生しているとworkload(負荷)増加の恐れがある
他雑談
- MVCCは理解に3年かかる。説明できるようになるのに8年かかる
- 神林さんのdb tech showcase2018の発表ですが、資料公開/ブログで再整理される予定があるそうです!
- ANSIのSQL標準の資料は、新しいものは有料だが、ベータ版は公開されていて読めるらしい
- プログラミング言語のコンペでSQLを使って2位になったチームがあったらしい?
- ISUCONではない。
- COBOLで作られたWEBサーバーがあるらしい?(プロジェクト)
次回は「3.13 TREE LOCKING」から!
*1:ロック解放は時間がかかるような処理なのか?
dbtech showcase Tokyo2018に参加
dbtech showcase Tokyo2018に参加
このカンファレンスは「プログラマのためのSQL」の参加者から聞いて知りました。 大企業/メガベンチャーのDBの運用ノウハウだったりデータベースベンダーの方から最新の製品テクノロジなどが楽しく聞けた3日間でした。
ストレージ
- A27:DBエンジニアのためにSSD Q&A集
SSDのセッション。内容は以下の4つ
#dbts2018
— yuYabu@転職中 (@yuyabu2) September 20, 2018
FW進化の歴史
0.何もしない(古いデータの読み取りがどんどん遅い)
1.読み出しごとにリフレッシュ(初回リードが毎回遅い)
2.定期的に強制リフレッシュ(余計な書き込みが発生する)
3.Patrol Read:アドホックにリフレッシュ(電圧が下がっている場所を発見する)
SSDはHDDより爆速で早い、程度の認識しかなく、そこまで興味はなかったのですが、twitterのタイムラインが盛り上がっていたので急遽参加しました。
SSDの仕組みから始まり、寿命やコントローラーの説明、NVMeの展望などが語られました。
SSDはファームウェアは順調に進化しているが、それを利用するOSやFSはまだまだ技術に追いついていない(特にNVMe)という印象を持ちました。
企業システム向けのSSDはまだまだ進化の余地があり、今後ますます注目が集まってくる分野になると思います。
MySQL 8.0
ドキュメントベースのNoSQLデータベースとして利用しつつ、jsonの任意のデータを選択した仮想列を作成してそちらをSQLから参照するというテクニックが披露されました(x dev API)。MySQL8.0では他にもWindow関数が入ったりして大きく標準SQLに近づいたというか、自分の中でMySQL株が上がりまくりです。
トランザクション理論
- A13・14:今後のDBのトランザクション処理のあり方について徹底討議する ~"InvisibleWriteRule: トランザクションの書込み最適化" を中心に
- C33:MVCCにおけるw-w/w-r/r-wのあり方とcommit orderのあり方の再検討~Sundial: Harmonizing Concurrency Control and Caching in a Distributed OLTP Database Management Systemを題材に
1日めのA13/14は忘れ物で*1遅れて参加したため、後半部分しか聞けませんでした。最近気になって購読し始めた「ぱと隊長日誌*2」の筆者の方や神林さん、kumagiさん(参加者)などなど、トランザクションに関する情報発信をされてる方々が勢揃いされていたので、面白いディスカッションだったと思う。
C33は事前に前倒しで開始する...との連絡が非公式にありましたが、5分前に到着したところすでに始まっており、前倒ししたのに10分程度延長されていた
DBTS2018 C33「MVCCにおけるw-w/w-r/r-wのあり方とcommit orderのあり方の再検討」にご興味のある皆様へ、神林さんから伺ったことを共有します。開演時刻を少し前倒しするかも(注:昨年も同様で、かつ終演時刻overの熱さ)。スライド公開予定:Noとなっているけど、公開するかも。(続く)#dbts2018
— ぱと (@pato_taityo) September 20, 2018
今日の神林さんの講演は予想通り前倒し開演、終演時刻ぶっちぎり(でも終わらない)だったな。でも、あの熱の入った講演スタイルは大好きだったりする。#dbts2018
— ぱと (@pato_taityo) September 21, 2018
発表内容としてはこちらの論文を読みながらMVCCやOCCを分散システムに適応するとどうなるか、という発表内容だった。
http://www.vldb.org/pvldb/vol11/p1289-yu.pdf
個人的に印象に残ったのが、
- Sundialのアルゴリズムではロックに頼らず、時系列順(Timestamp Ordering)に頼ってデータの整合性を担保する
- サイト間で物理時間は同期しない。*3同期するのは順序のみで、順序同期なら技術的に可能らしい
- 実行順序を工夫することで、発生順ではありえない操作が実現できる
r1(x2)w2(x2)c2c1→w2(x2)r1(x2)c2c1
あとちなみに別セッションですが...
Amazonのマルチマスタなデータベースに関して分散システムの勉強会で話題に登りましたが...
#dbts2018
— yuYabu@転職中 (@yuyabu2) September 21, 2018
amazonのマルチマスターのコンフリクト解決はcommit先勝ち。
競合する後続のトランザクションはどんなに長くてもロールバック(例外もある)
書き込み競合は先勝ちとなっているようです。ではデッドロック検知は...気になりますねぇ(やっぱりタイムアウトなんでしょうか?)
大企業のDBA
他にもLINEさんのセッションやリクルートさんのセッションが面白かったです。 普段は聞けない大企業のDB運用事例について聞くことができました。
#dbts2018
— yuYabu@転職中 (@yuyabu2) 2018年9月20日
LINEが使ってるデータベース関連プロダクト
・REBMS
MySQL
Oracle
SQLServer
CUBRID(韓国Narva製)
・NOSQL
redis
mongoDB
HBase
elastic
※redisとMySQLがメイン
#dbts2018
— yuYabu@転職中 (@yuyabu2) September 21, 2018
NoSQLはキーバリュー,ドキュメント型
とかで分類するのは古い
NoSQLの新しい分類方法
- レスポンスタイム追求型
- 開発容易性追求型
リクルートさんの方は社内事例の紹介という訳ではなく、昨今話題の様々なデータベース関連製品の紹介&整理でした。分量が多すぎて理解しきれていませんが、格DBやその使い分けに関してわかりやすく紹介されていました。
#dbts2018
— yuYabu@転職中 (@yuyabu2) September 20, 2018
LINEではMySQL Query Replayerを開発中!
ネットワークパケットからクエリを取得してリプレイするツール。
来年のdbtech show caseで発表予定か!?
LINEさんは自社でMySQL関連のツールを色々作られているそうです(面白そう) 1日目のYahooさんの発表も聞いておけばよかったと後悔。
勉強時間の大半をRDBMSに費やしていましたが、今までDBAの方のお話を聞く機会が今までなかったので刺激的でした。
*1:メガネ...これがないと発表会では何も見れない
プログラマのためのSQL 読書会(27)に参加
余談ですが参加者にdbtech show case tokyo 2018の参加者も多かったので、そちらの話題で雑談などが盛り上がりました。*1
「29.7ビット単位の集約関数」から読みました。
- 作者: ジョー・セルコ,Joe Celko,ミック
- 出版社/メーカー: 翔泳社
- 発売日: 2013/05/24
- メディア: 大型本
- この商品を含むブログ (16件) を見る
- 「30.高度な集約、ウィンドウ関数、OLAP」にあるスノーフレークとは
適切に設計されたOLTPデータベースは正規化されている。通常、DWHはスタースキーマスキーマまたはスノーフレークスキーマを採用しており、これはかなり非正規化されている。
- スノーフレークはITでは多義語なので注意すること
- Amazon RedShift
- https://kyrt.in/2014/06/08/snowflake_c.html
- twitter社が作成した分散環境でユニークなIDを振る仕組みと、DWHでのテーブル設計パターンの2つともがスノーフレークを表しているような印象を受けました。
ペタバイト以上のデータを持つ企業
がペタバイト以上のデータを持つ企業だと書かれているが、 このほんの情報は古く、2014年時点では売上10億ドル以上の 企業の56パーセントが 1PB以上のデータを管理している*2
MySQL 8を試したくbrew upgradeしたところ、前バージョンで正常終了してないため起動できない的なエラーで怒られてるなう。
— yuYabu@転職活動中 (@yuyabu2) September 19, 2018
MySQL Sandboxで独立した環境を構築できる
- dbdeployerも検討すべき。
MySQLはなぜ5の次が8なのか
11月にpostgreSQLのカンファレンスおすすめ
P.562のクエリがおかしい
▼P.562 SELECT B.region_nbr, S.city_id, SUM(S.sales_amt) AS total_sales FROM SalesFacts AS S, MarketLookup AS M WHERE EXTRACT (YEAR FROM trans_date) = 2011 AND S.city_id = B.city_id AND B.region_nbr = 6 GROUP BY ROLLUP(B.region_nbr, S.city_id);
- Bという別名はどこから出て来たのか。(Mではないのか?誤植?)
このSQLを実行できるTableが書かれていないのでそちらも欲しい
- 最新のMySQLにwindow関数に対応した
- 最新のSQLiteはWindow関数に対応した
- PostgreSQLの挙動に準拠している
CUME_DIST()
関数- 初めて見たので検証予定
Window Frame
- 理解しきれてないので検証予定
前職ではウインドウ関数を多少していたのですが*3、WindowFrameを弄ったりは普段やりません。*4 ので、この辺は技術検証の必要があるかなと思います。
次は「30.6ベンダー拡張」から!
分散処理本第38回に参加
Distributed Computing: Principles, Algorithms, and Systemsを読む勉強会です。やはり難しいので少し予習していきました。アルゴリズムの分類までは一応軽く読んで概要をつかんでから臨みました
- 分散システムに置けるデッドロックの検出アルゴリズムの分類
- path-pushing
- edge-chasing
- diffusion computation
- global state detection.
- 10.6 Mitchell and Merritt’s algorithm for the single-resource model
- 余談:ACM Degital Libaryは高い
予習をしてブログの下書きを作っておくと、感想のポストがサクッとかけて良いですね。
Distributed Computing: Principles, Algorithms, and Systems
- 作者: Ajay D. Kshemkalyani,Mukesh Singhal
- 出版社/メーカー: Cambridge University Press
- 発売日: 2011/03/03
- メディア: ペーパーバック
- この商品を含むブログを見る
分散システムに置けるデッドロックの検出アルゴリズムの分類
- path-pushing
- edge-chasing
- diffusion computation
- global state detection.
出典:E. Knapp, Deadlock detection in distributed databases, ACM Computing Surveys, 19(4), 1987, 303–328.
※詳しい方が概要を知っているがその分類名を知らない、ということが発生していたので、一般的な分類ではないのかもしれない。
path-pushing
各サイトがWFGを送り合いグローバルなWFGを構築する。 送信しながらどんどんWFGを更新してデッドロックの発生、検知を明らかにして行く
edge-chasing
グラフのエッジに剃ってprobesと呼ばれる特殊なメッセージを送信して行く。 以前送信したprobeと同じものを送信した場合、それでcycleを検出できる
diffusion computation
deadlockが発生していれば帰ってくるようなエコーメッセージを送る。
よく解らん?という話になった
参考にしてある論文は以下のもの
Herman and K. M. Chandy, A Distributed Procedure to Detect AND/OR Deadlock, Technical Report TR LCS-8301, Department of Computer Sciences, University of Texas, Austin, TX, 1983.
本書記載のアルゴリズム例は2つあり、
- Chandy–Misra–Haas algorithm for one OR model
- Chandy–Herman algorithm
前者はWikipediaの記事があった
https://en.wikipedia.org/wiki/Chandy-Misra-Haas_algorithm_resource_model
CMHアルゴリズムとしても有名らしい
global state detection.
分散システムの各スナップショットからデッドロック有無を確認する。しかし以下の条件が必要である
(i) a consistent snapshot of a distributed system can be obtained without freezing the underlying computation.
(ii) a consistent snapshot may not represent the system state at any moment in time, but if a stable property holds in the system before the snapshot collection is initiated, this property will still hold in the snapshot.
10.6 Mitchell and Merritt’s algorithm for the single-resource model
- WFGの逆向きにprobを飛ばす
- edge-chasingアルゴリズムのうちの一つ
アルゴリズムとしてはpublic/privateなlabelを使う 文章化するのがちょっと難しいが一言で表すなら
- 待ち状態に対して2種類(private/public)のラベル作成し値zを与える
- 下の例はu->v間の待ちを表しているこのzはu+vより大きな値かつユニークでなければならない
- この操作を待ちの連鎖が終わるところまで続けて行く
2週することで図のDetect
の状態が発生が把握できる(1週しただけだとDeadlockかどうかわからない)
p360の図は誤植
- Figure 10.2 The four possible state transitions [22]
という図があるが元ネタが「E. Knapp, Deadlock detection in distributed databases, ACM Computing Surveys, 19(4), 1987, 303–328.」という論文の図であり、引用するときに一部記号が間違っている。
また10.6
は本書中の記載のみだと理解が辛く、引用元の論文をよく読み込まないと何を行っているかわからない。
余談:ACM Degital Libaryは高い
500ドルくらいするらしい。。。
次回は「10.7 Chandy–Misra–Haas algorithm for the AND model」から!
a tour of Goをやった
Goならわかるシステムプログラミングで推奨していたのでとりあえず一周して見た*1
https://go-tour-jp.appspot.com/list
Go言語の文法については、全くのプログラミング初心者でなければ、tour of Goという公式のチュートリアルを一通りこなすだけで、本書の範囲なら十分理解できるでしょう
Goならわかるシステムプログラミングp4より抜粋
と書かれていたのでとりあえずやっておこう、というつもりで進めたのだが。。。 だらだらやったのもあってか1.5日ほどかかった。
- フィボナッチ
- ワードカウント?的なやつ。一応テストは全てパスした
- なんか画像を作るやつ
- ASCII文字 'A' の無限ストリームを出力する Reader
- io.Readerをラップした暗号復号処理(rot13)
- conncurenncyを使った二分木探索
- mutexを使ったクローラー
- 他:違和感のある翻訳
- 感想
とりあえず自分は日頃競プロ的な頭を使うプログラミングをやらないので、 プログラミング能力が劇的に落ちていることを実感した。
時間をかけて競プロを強めようとは思わないが、アルゴリズムとかのエンジニアとしての基礎的な部分を固める必要があると再度認識した。
コードはあまり人に見せられるような綺麗なものではないけど、時間がかかった課題のものを中心に公開しておきます。
フィボナッチ
https://go-tour-jp.appspot.com/moretypes/26
DRYにものすごく反しているような???
package main import "fmt" // fibonacci is a function that returns // a function that returns an int. func fibonacci() func() int { count := 0 v1 := 0 v2 := 0 value := 0 return func() int { defer func() { count++ }() if count == 0 { return 0 } else if count == 1 { v1 = 0 v2 = 1 return 1 } else { value = v1 + v2 v1 = v2 v2 = value return value } } } func main() { f := fibonacci() for i := 0; i < 15; i++ { fmt.Println(f()) } }
ワードカウント?的なやつ。一応テストは全てパスした
https://go-tour-jp.appspot.com/moretypes/23
package main import ( "golang.org/x/tour/wc" "strings" ) func WordCount(s string) map[string]int { wordlists := strings.Fields(s) countMap := make(map[string]int) for _, v := range wordlists { countMap[v]++ } //return map[string]int{"x": 1} return countMap } func main() { wc.Test(WordCount) }
なんか画像を作るやつ
https://go-tour-jp.appspot.com/moretypes/18
package main import "golang.org/x/tour/pic" func Pic(dx, dy int) [][]uint8 { value := make([][]uint8, dy) for i := 0; i < dy; i++ { value[i] = make([]uint8, dx) for j:=0;j<dx;j++{ value[i][j] = uint8(i^j) } } return value } func main() { pic.Show(Pic) }
生成する画像は、好きに選んでください。例えば、面白い関数に、 (x+y)/2 、 x*y 、 xy などがあります。
ASCII文字 'A' の無限ストリームを出力する Reader
package main import "golang.org/x/tour/reader" type MyReader struct{} // TODO: Add a Read([]byte) (int, error) method to MyReader. func(r MyReader) Read(b []byte) (int ,error){ b[0] = 'A' return 1,nil } func main() { reader.Validate(MyReader{}) }
io.Readerをラップした暗号復号処理(rot13)
rot13Reader(io.Readerをラップして換字式暗号を標準入出力に変換してだす)
readerが最後にerrorとしてio.EOFを返すのが解らずに、1時間ほど試行錯誤した。
package main import ( "fmt" "io" "os" "strings" ) type rot13Reader struct { r io.Reader } func (r2 rot13Reader) Read(p []byte) (n int, e error) { i := 0 b := make([]byte, 1) for { _, err := r2.r.Read(b) //fmt.Printf("n = %v err = %v b = %v\n", n, err, b) //fmt.Printf("b[:n] = %q(%v)\n", b[0], b[0]) if err == io.EOF { break } value := b[0] //文字の場合のみ暗号置換を実施する if 64 < b[0] && b[0] < 91 { value = value + 13 if value > 90 { value = value - 26 } } if 96 < b[0] && b[0] < 123 { value = value + 13 if value > 122 { value = value - 26 } } //fmt.Printf("lot13 = %q(%v)\n", value, value) p[i] = value i++ } return i, io.EOF } func main() { s := strings.NewReader("Lbh penpxrq gur pbqr!") r := rot13Reader{s} //b := make([]byte, 100);r.Read(b) io.Copy(os.Stdout, &r) }
解読後は普通の文章になっているので多分あっていると思うが、if文の境界値条件はきちんと検査していないのでバッグっているかもしれない。
conncurenncyを使った二分木探索
https://go-tour-jp.appspot.com/concurrency/8
package main import ( "fmt" "golang.org/x/tour/tree" ) // Walk walks the tree t sending all values // from the tree to the channel ch. func Walk(t *tree.Tree, ch chan int) { //fmt.Println(t) //左があるときはどんどん左に行っちゃう if t.Left != nil { Walk(t.Left, ch) ch <- t.Value if t.Right != nil { Walk(t.Right, ch) } //左がなくなったけど右がある場合はそっちに行く } else if t.Right != nil { ch <- t.Value Walk(t.Right, ch) } else { //葉 ch <- t.Value } } // Same determines whether the trees // t1 and t2 contain the same values. func Same(t1, t2 *tree.Tree) bool { ch1:=make(chan int,10) ch2:=make(chan int,10) Walk(t1,ch1) Walk(t2,ch2) for i:=0;i<10;i++{ v1:= <-ch1 v2:= <-ch2 if(v1!=v2){ return false } } return true } func main() { fmt.Println("test") /* ch := make(chan int) go Walk(tree.New(2), ch) count := 0 for i := range ch { fmt.Println(i*10) count++ if(count == 10){ //closeするタイミングをどこに入れるか解らなかったので //呼び出し側にいれた。こういうプログラミングは良くないと思う close(ch) } } */ b1:= Same(tree.New(1), tree.New(2)) fmt.Println(b1) }
mutexを使ったクローラー
https://go-tour-jp.appspot.com/concurrency/10
Crawlメソッドの呼び出しを並列に(goroutine)にしなければ動く。 並列にするとなぜか正しく動かない。これは自分がmutexとか並列プログラミングにまだまだ無知だからだと思う。 とりあえず私が並列プログラミングをやるとdeadlockだらけになることがわかった。
package main import ( "fmt" "sync" ) type Fetcher interface { // Fetch returns the body of URL and // a slice of URLs found on that page. Fetch(url string) (body string, urls []string, err error) } // Crawl uses fetcher to recursively crawl // pages starting with url, to a maximum of depth. func Crawl(url string, depth int, fetcher Fetcher) { // TODO: Fetch URLs in parallel. // TODO: Don't fetch the same URL twice. // This implementation doesn't do either: if depth <= 0 { return } mux.Lock() if check[url] == 1 { mux.Unlock() return } check[url] = 1 body, urls, err := fetcher.Fetch(url) mux.Unlock() if err != nil { fmt.Println(err) return } fmt.Printf("found: %s %q\n", url, body) for _, u := range urls { //go Crawl(u, depth-1, fetcher) //並列だと正しく動かない Crawl(u, depth-1, fetcher) } return } func main() { check = make(map[string]int) Crawl("https://golang.org/", 4, fetcher) } // fakeFetcher is Fetcher that returns canned results. type fakeFetcher map[string]*fakeResult type fakeResult struct { body string urls []string } var mux sync.Mutex var check map[string]int func (f fakeFetcher) Fetch(url string) (string, []string, error) { if res, ok := f[url]; ok { return res.body, res.urls, nil } return "", nil, fmt.Errorf("not found: %s", url) } // fetcher is a populated fakeFetcher. var fetcher = fakeFetcher{ "https://golang.org/": &fakeResult{ "The Go Programming Language", []string{ "https://golang.org/pkg/", "https://golang.org/cmd/", }, }, "https://golang.org/pkg/": &fakeResult{ "Packages", []string{ "https://golang.org/", "https://golang.org/cmd/", "https://golang.org/pkg/fmt/", "https://golang.org/pkg/os/", }, }, "https://golang.org/pkg/fmt/": &fakeResult{ "Package fmt", []string{ "https://golang.org/", "https://golang.org/pkg/", }, }, "https://golang.org/pkg/os/": &fakeResult{ "Package os", []string{ "https://golang.org/", "https://golang.org/pkg/", }, }, }
他:違和感のある翻訳
呼び出す 具体的な メソッドを示す型がインターフェースのタプル内に存在しないため、 nil インターフェースのメソッドを呼び出すと、ランタイムエラーになります。
https://go-tour-jp.appspot.com/methods/13
編集履歴を辿って原文を確認すると以下のようであった
Calling a method on a nil interface is a run-time error because there is no type inside the interface tuple to indicate which concrete method to call.
https://github.com/atotto/go-tour-jp/commit/123f593e8270035b7f59a8d4eaa0e61bbee98239
具象メソッドを含むinterfaceタプルが存在しないのでnilインターフェースの呼び出しはエラーになります。くらいが妥当な気がする?
というかinterfaceタプル、ってなに?っていう感じでgoをそこまでわかっていないので具体的に今どういう役が適切かは提案できない。
https://qiita.com/umisama/items/e215d49138e949d7f805
だたgoのnilはJavaのnullとも違うし、nil自体がnil型のような特性を持っているような振る舞いがあるようなので、 この辺りは今後注意して学習して行きたい。
感想
今までは写経中心だったり、ロジックというよりもAPIのドキュメントを調べて書かれている通りに実装することが中心だったが、Goできちんとプログラミングを書くのは初めてだったのでいい経験になったと思う。
何よりも、tour of Goをやらねばいけない、という憑き物のようなものが落とせてよかった。
*1:と行っても周回するつもりはあいrません