奇特なブログ

「殊勝に値する行いや心掛け」を意味する、奇特な人になる為のブログです

システム開発における自動化の一例(あくまで一例)

こちらでは、すっかりご無沙汰しております。
まず、前回 2015年の振り返りと2016年の展望 - 奇特なブログ の年末年始に予告した記事は、
別に忘れてはいないんですけど、
内容があまりにも壮大になってしまいそうなのと、
どう書くかで悩んでいる(&調査中)ので、
時期未定に変更します。すいません。
対象になっている本を読んだ方が早いと思いますね、正直。


さて、本題なんですが、
最近「自動化」について考える事があったので、
これまでに見聞きした自動化手法なんぞをメモしておこうかと思いまして。
なので、「一例」なんですけど、
とりあえず以下の様な感じです。
あと、実装が簡単と思われる順番に書いてます。


1.この時間からこの時間まではイベント(別にソシャゲに限らず)を開催中にして、
時間外だったら、非開催中に自動で切り替わるようにして欲しい

以下が、方法(の一例)です。


方法:
DB(CSVとかでも良いけど)に、
イベント情報のテーブルを作り、その中に開始日時と終了日時を持たせる。
そして、イベントページ(仕様によってはTOPページとかも)にアクセスしたら、
アクセスした「サーバー(クライアントはダメ)」の現在日時が、
イベント開始日時と終了日時の範囲に入っているかチェックする。
入っていたら開催中、逆なら非開催中。


まぁ、これは簡単かなぁと。


2.指定時刻になったら、指定したファイルを自動で本番に反映してほしい

ここ(に限らない気もするが)は、やり方が以下の様に複数考えられますね。
あと、ここの(1)~(3)は、この後も出てくるので注意です。

(1)crontabに指定時刻を登録しておく場合
(2)DB(何度も言うが、別にDBじゃなくても可)のテーブルに指定時刻を登録しておく場合
(3)crontabに定期巡回をさせる場合

で、この場合は(1)が一番自然で簡単かなぁと思われます。
次が(2)で、(3)は出来るというよりやっちゃダメ(高確率で事故りそう)と思われます。
で、(1)だと以下の様な感じで。


方法:
crontabにファイルの反映(デプロイ)を開始したい時刻と、
デプロイするシェルスクリプト(ある現場、多いでしょ)を登録しておく。
デプロイするシェルスクリプトは、反映したいファイルパスが書かれているファイル名リストを参照し、
そのファイルのみを、本番に反映させる。
本番反映が終了したら、crontabの該当行はコメントアウト(しなくても良い気もするが)しておく。


ここは、「ファイル名リスト」って所が若干手間かなぁ・・・
コミットしたら、フックスクリプトで、そのファイル名リストを書き換えれば良いか(笑)
指定時刻も書き換え?出来るとは思いますけど、「こういう系って、あんまりやると事故ります」よ。
なので、この辺までかなぁと。


3.指定時刻になったら、自動でテストツールを実行して欲しい

ここは、例えば毎日何時って決まってるんだったら、
上記の(1)が一番かなぁと。
crontabの編集NGなら、(2)もありでしょうけど。
(3)は「頻度による」としか。


方法:
crontabにテストツールの実行を開始したい時刻と、
テストツールの実行コマンドを登録しておく。


で、ここから( or ここで)、カバレッジを取るだの何だのは、現場の方針次第ということで。
あと、上記2と合わせると、Jenkins不要説(まともに使った事無いので、これだけじゃないのかもしれないけど)も(笑)
いや、だって僕の口癖は「面倒だなぁ」ですから、
「覚えなくて良いなら、覚えたくない」んですよね(苦笑)


4.指定時刻になったら、DBのテーブル内の参照するレコードを変えてほしい

これは、ちょっとマニアック(別に、そう難しくはないと思われますが)かも。
あと、トランザクションデータだと、この辺はどうかなと思いますので、
マスタと履歴データ(さすがに怖いが、こっちは消す方でも使えるかも)が対象かなと思いますね。
あと、上記の(1)だと管理大変そうなので、
(2)か(3)かなぁと。


方法:
DB(何度もry)に、スケジュールを管理するテーブルを作り、
指定時刻になったら、
「このテーブル(テーブルAとする)の、この辺を参照する様にする」というレコードを「開始日時と終了日時」も合わせて登録する。
テーブルA側には、上記テーブルの「この辺を」と一致する列を作り、
列が一致しているレコードのみを参照する様にする。
そして、テーブルAからデータを取得する時には、
事前にサーバーの現在時刻に一致するレコードを、スケジュール管理テーブルから取得(この時、絶対にキャッシュから取ってはいけない)し、
「どの辺を参照するか」を決めてから、テーブルAのデータを取得する。


これ、「どの辺を参照するかを変えるじゃなくて、書き換えたら?」って意見もありそうで、
まぁ、確かにそっちでも全然良いと思いますね(書き換え後のキャッシュ消し忘れに注意)。
なので、ココは議論かなぁと。


5.指定時刻になったら、目覚まし時計代わりに、自分のPC内のアダルトDVDの再生が始まる(笑)自動化版Iot?(笑)

wwwwwwwwwwwwwww
で、ココは、実装は全く思い浮かばないですけど、趣味目的で作ってみるのもアリかも(笑)


ということで以上です。
あとは「番外編」として、
自動化とは全然関係無い、以下の様なモノを考えてみました。
・・・多分、以下の本の「キチガイ(では無いという人も、結構いそうなのが怖いですが)要求」辺りから、連想したと思われます。


www.amazon.co.jp


番外編:ファイルのバージョン管理を、バージョン管理ツールを使わないで行いたい

まず、以下の様なテーブル(書式などは若干適当)を作る。


CREATE TABLE file_version_history (
revision INT NOT NULL COMMENT 'リビジョン番号',
no INT NOT NULL COMMENT '識別番号',
file_name TEXT NOT NULL COMMENT '更新されたファイルのパス情報',
change_type INT NOT NULL COMMENT '追加や削除などの更新種別',
file_bosy TEXT NOT NULL COMMENT 'ファイルの中身の内容',
insert_date DATETIME NOT NULL COMMENT '追加日時',
PRIMARY KEY (revision, no)
) COMMENT 'ファイルのバージョン管理テーブル';


次に、クライアントツールやWebでの管理ツールを作り、
そこに、「コミットする」という項目(Webならボタンとか)を作る。
コミットする機能を使用すると、
上記テーブルにレコードが登録される。
差分を取りたい場合は、
上記テーブルの情報と現在の情報を比較する。
リバートしたい場合は、
上記テーブルの対象リビジョンのレコードをDELETEし、
DELETEしたレコードは、同じ様な構造のバックアップテーブルに入れる。
リバートした内容を更にリバートしたい場合は、
バックアップテーブルから、レコードを取ってきて入れ直す。
フックスクリプト?→あくまで番外編なので、一旦ここまで。

こんな感じですかね。

例によって、ご感想などをお待ちしております。

2015年の振り返りと2016年の展望

さて、毎年恒例となりましたが、今年も書きましょう。
で、書く前に「ネタが凄い多くなるかも」と思っていたんですけど、
全部覚えている(特にメモも取ってないので)わけでもないので、
思い付いた内容から書いていきたいと思います。
まずは、2015年の振り返りから。


1.お金を持っていると、出来ること(選択肢)が増える


これが、まぁ2014年もそうだったし、
考えてみたら昔パチプロをやっていた時もそうだったんですが、
特に実感した所ですね。
だって、「働いた月数」が、
2014年は「8ヶ月」、
2015年は「4ヶ月」、
パチプロ(パチプロの定義によっては仕事かもしれないですけど、少なくとも僕のやり方は外れていたかな)の時は「0ヶ月」でしたから。
というか、2015年酷いなコレ(苦笑)
あ、講師の仕事は月数に含めていないですが。


で、上記の場合だと、「仕事をしないという選択肢が増える」ですかね。
まぁ、勿論他にも色々ありまして、


・より美味しい料理を食べることが出来る
・色々な所に旅行に行くことが出来る
・色々な所に寄付する事が出来る
・自分の好きな相手に、プレゼントをすることが出来る


とか、書きだしたらキリないでしょうけど。
で、上記の項目の接頭辞に「お金を持っていると」を付けてみるとピンと来るんじゃないかなと思うんですけどね。


ちなみに、仕事に対してこの事実を悪用すると、
「給料を多くすると辞められる可能性が高くなるので、給料も高くせずに且つ、
転職活動をさせない為に仕事の量を大量に押し付けて、プライベートな時間を減らす。
で、それでも止める様なら、同業(競合)他社への転職禁止的な誓約書なりに同意させたりしてプレッシャーをかける」
という様な、結構ざっくりですが、ブラック企業の経営者が考えそうなロジックにもなったり(苦笑)
ちなみに、最後の項目については、
「機密と定義されている情報を持ち出して、他社でのビジネス展開に活かそうとした」ならNGかも(専門分野じゃないので要確認を)ですが、
単純に、同業他社への転職禁止なら、憲法職業選択の自由の条文の方で引っ掛かると思いますね。


で、まぁ、上記の件については「気を付けましょう(僕自身もですが)」としか言いようがないですけど、
話を戻して、とにかく「お金を持っていることに伴うメリット」というのを再実感出来たココ2年間だったなと。


なので、「お金を幾ら頂けるのか」は拘った方が良い(勿論、拘れば拘る程仕事減るので、そこは注意ですが)と思いますし、
「収入アップに繋がりやすい努力(それが全てではないのは知ってます、というか元々その傾向強い)」の比率を高めるのが大事だろうなぁと。


ちなみに、こういう話するとよく、
「お金を持っていたって幸せになれるとは限らないでしょ?」的な感想を持つ方もいらっしゃる様ですけど、
えぇ、まぁこれは特に否定もしません。
ただ、幸せって「お金で買う」系の幸せもあるんですよね。で、貧乏だとそれが出来ない。
例えば、「お金が無いからゲーム(ココは自分の好きな趣味でOK)買えないので、幸せを感じにくい」とか。


なので、幸せと一言でいっても色々とあるので(お金で買えない幸せも当然ありますし)、
一概には言えないかなと。


長くなりましたけど、ひとまず1番はここまでにします。


2.禁煙や健康面


これは、つい最近の話ですけど、
先日、気管支炎(正確にジャッジするのは難しいみたいですし、とりあえず肺炎では無かった)にかかりまして、
2週間ぐらい、咳が止まらなかった(具体的には、痰が喉に溜まっている状態)と。
今も、まぁ「完治」はしてないですかね。なので、カラオケには若干悪影響はありそう(笑)


で、これだけだと単に「ただ、風邪引いただけでしょ」なんですけど、
僕の場合、生まれてから「ずっと」、「風邪を引いたとしても、せいぜい3日もあれば完治する」のが特徴でして、
なので、これは珍しいと。まず、これが一つ。


で、もう一つは、同業の知り合いのフリーのエンジニア(スキルは僕より10倍以上、上かな)が倒れて1か月以上入院し、
生死の狭間を彷徨ったらしいと。
で、どうやらコレ、そう大げさな話でも無かったみたいなんですね。で、これが二つ目。


で、上記二つの話を合わせると、
まぁ、元々どのくらい健康体質なのかってのはあるかと思うんですが、
それでも、多分「働き過ぎによる疲労の蓄積」とかはあるのではと。
かといって、じゃあ働かなければ良いという選択肢も、
今後10~20年という様なスパンで見た場合には難しいだろうなぁとも思うので、
結論として、多分「長生きは難しいなぁ」と。
僕個人に関しては、このままだと60歳になる前に死んでる気がしますね。
上記の気管支炎は、ヒヤリハットでいう「ヒヤリ」じゃないかと思ってますし。
だから、未婚の女性からすると、僕と結婚するのはリスクが高いかもしれないですね。


ただまぁ、気管支炎がきっかけで禁煙も出来る事が分かった(喫煙歴20年ぐらいだったんですが)ので、
良い事もあった(というか作った)んですけどね(笑)


で、根本的な改善については、この後の3と4も若干絡むんですけど、
基本的にはかなり難しいのではとも思いますね。
少なくとも、エンジニア全員が取れる選択肢でも無いでしょうし。


あと、健康に関しては、そういうば以下の記事もありましたね。


gallu.hatenablog.com


3.クビになった件


そういえば、これはまだ公にはしてなかったんですけど、
振り返るとこれは重要だなぁと思った出来事を一つ。
今年の5月に講師の仕事をしていた時だったんですけど、
「研修初日で、もう次の日からは来なくて良い(その日の講師料は頂きましたが)」と言われたんですね。
で、聞いた時には「え~、そんな予兆全く感じなかったし、気になる点あるなら言ってくれれば良いのに。あと、たった一日で判断されるの?」という感想だったんですね。
なので、2~3日、ショックで寝込んだ記憶が(苦笑)
ただまぁ、高給(少なくとも、時給換算で今までの開発案件より高かったのは事実)を払うクライアントからすると、
「こっちは高いお金を払っているわけだし、提供内容がコストに見合わなければ切らざるを得ない」というロジックは当然あるだろうなぁと。
あと、「改善しますって口で言われても、本当に改善出来るのか分からないし」という話も。
で、前者は僕が逆の立場だったら(なった事無いけど)そう思いますし、
あと後者に関しては、開発の案件で役職が上の人が「私の責任です。今後、改善していきます」って言ってるけど、
ちっとも改善してないし、改善する気が本気であるのかも分からないしって辺りを考えると、「妥当かもなぁ」とも思いますね。
何というか、意外と日本(といっても、前述の通り場所によるわけですが)ってビジネスに対して「甘い」のかもなぁと、この辺見ると。
いやだって、「結果が出ないなら、降格させて担当変えるなり、最悪クビ切れば良い」じゃないですか。
特に、外注なら尚更。
他の人はどうか知らないですけど、少なくとも僕は「いつクビになるか分からない」と思って仕事してますし。
前述のクビになった出来事の後は、特にそうですね。
で、こう思えた事を考えると、前述の出来事も良かったかもね。


で、この辺が4にも出てくる「雇用の流動性」にも関連あるなぁと。
多分、「雇用の流動性」が無いと、仕事に「緊張感が生まれない」って一面はあるのではと。


4.海外について


この辺は確か、今年の4月に、「シアトルで日本人エンジニア募集」みたいな話をTwitterで知って(スキルがミスマッチでダメでしたが)、
あと、以下の本も最近出て読んで(っていうのと、勿論上記の国内の状況もありますが)視界に入る様になりましたね。


www.amazon.co.jp


いや、話はかなり単純でして、
「日本でフリーでエンジニアやっていけないなら、海外(特にアメリカに限らず)行くしかないよな」という(苦笑)
あと、上記の本については、かなり思う所ありましたので、
出来れば、正月休み中に、もう一つの方のブログ http://d.hatena.ne.jp/kitoku_magic/ に、
書きたいと思います。
今の所、この本の他の人の書評を読んでる限り、あまり踏み込んだ内容を書いてる人がいなかったとも思いましたしね。



では、2015年の振り返りはここまでで、
ここからは、2016年の展望を。


1.開発案件


出来ればゲーム以外の案件(ゲーム以外だと単価下がるとか聞きますが、ホントかソレ?)が良いなぁと。
いや、ゲームだけは、どうも異常に拘りが強いせいか、
以下の記事の症状がねっていう(苦笑)


gallu.hatenablog.com


あと、この辺は例のエロの方も拘りが強い(下半身専門で、キモイ系)気がするんですけど、
最近、「上半身もアリじゃないか?(上半身だと、女性の"顔"が見えるw)」とも思う様にもなってきており、
DMMとかで、アダルト関連の案件をやってみたい気も(笑)
あ、ただ上半身でも下半身でも、キモイ系だけは共通しているかもしれないですね(苦笑)


2.講師案件


専業では考えていないですが、
「口ベタ」を改善したいかなぁという気持ちもあり。
あと、単純に上記のクビになった件のリベンジも(笑)


3.英語


上記の海外云々の話も勿論ありますけど、
別に国内にいても「英語のドキュメント(最近、よく見かけるので)」を読むのに困るので。
ちなみにこの辺、期間(何ヶ月が妥当かは別途考えるとして)を区切って、一気にTOEIC800点(じゃなくても良いかもしれないが)とかを狙った方が良いんじゃないかと思っています。
「期間を長く取って、コツコツと覚えていく」ってのは、あまりピンと来ない(頻繁に使う場合には、左記の方法で良いと思うんだけど)ので。


4.雑談会の再開催


そういえば、すっかり忘れてましたけど、以下の記事の事ですね。
「基本理念」的な話は、第一回の方に書いてます。


kitoku-magic.hatenablog.com


ただまぁ、これ系って別に、何時でも良いっちゃ何時でも良いんですけどね。
ただ、イベントを立てた場合には、「他の用事は絶対に入れない」ってだけなので、
気軽にお問合せ下さいということで。


5.ゲームから学ぶ系


いや、別に今でも興味は全然あるんですけど、何しろ「お金に繋がりにくい」ので。
ちなみに、夏にこれと同じ様な内容の以下のイベントに行ってきましたけど、
そこでも、「予算(ここでは研究の事)不足」については聞きましたね。


2015年夏季研究発表大会 | DiGRA JAPAN


で、予算が付かない原因は色々とあると思うんですけど、
仮に、政府がOK出したとしても、
国民側の猛反発もそれなりにありそうに見える(僕がまともだと思った人でも、この分野はどうも意見が割れるみたい)ので、
言う程簡単じゃないなというのが、個人的な印象ですね(苦笑)
なので、ココ2年は、この分野にかなりの時間を割いて(仕事やってない時期は、殆どコレですし)きましたが、
少し、トーンダウンすると思います。
いや、何よりもお金の問題なんですけどね。


6.自作アプリなど


まず、ホームページはリニューアル予定(特に、書籍ページ。個人的に使いにくくなったので)ですと。
で、これは1年もあれば、さすがに終わると思います。
あと、以下にも書いたエロアプリの件。


kitoku-magic.hatenablog.com


う~ん、ひとまず「可愛くて恋愛要素が強い」系と、
「エロ要素が強い系」で二つありまして。
で、前者だと、設問ネタが少ない・当たり障りがあまりないって所から、多分「売れない」んですね。
ただ、逆に後者だと、仮に売れた場合(といっても、売るのすら難しいですが)に「批判を浴びやすい」というのもあり。
先日の、おっぱい募金反対の声とか見ても。
ただまぁ、個人的には批判についてはあまり気にしてなくて、
どっちかというと、以下の刑法175条の方が引っ掛かってるんですけどね。
「文章」も、対象に入ってますので。


刑法第175条 - Wikibooks


あとは、まぁ類似としては、以下の様なのも見つけた(ホントかどうかは知りませんけどね)ので、
どっちかというと、一般人の批判とかよりは、警察の動きの方が気になるなぁと。


d.hatena.ne.jp


ただまぁ、ここで問題なのは、
文章とは言うものの、「パンツ」とか「お尻」とか「おっぱい」と書くだけでNGなのかといったら、
そんな事はない(もしあったら、それこそ社会がおかしいわ)わけで、
「線引きのライン」があるわけですが、これがどうも分かりにくいと。
なので、この辺がある程度見えないと、ビジネス展開は難しいですね。


ちなみに、この分野、おそらく海外での展開は難しい(日本より、この辺うるさい様に見える。宗教もあるかな?)でしょうね。
そういう意味で、グローバル的にみたら「ダメ」なんでしょうけど、
「日本独自」というのを強みにするなら「アリ」って感じでしょうね。
で、どっちが良いかは、国の展望(目指す方向性とか)によるんじゃないかなと。
ひとまずは、ここまでにします。



という感じで、2016年も盛り沢山な感じですが、どうぞよろしくお願い致します。

Webアプリにおけるプログラムのパフォーマンスチューニング

さて、ちょっと予定には無かったんですけど、

最近この辺を考える事がやけに多く、

ということで、こんな記事を書いてみようかなぁと思います。


ちなみに、非エンジニアがエンジニアを評価(出来るのか?って話もありますが)するにあたって、

チューニングをした結果の「レスポンスが10秒→1秒になった」というのは、

スキルジャッジとしては分かりやすい指標だろうなぁとは思うので、

そういう意味でも「チューニング実績」というのは良いのかもと思いますね。


では、本題です。

が、急いでいる人?の為に、結論を先に。


1.JOINが出来るなら、まずはJOINを検討。あと、OFFSETとLIMITが使えるなら、よりベター。

2.JOINが出来ないなら、NoSQLを上手く使う。その際、出来るだけループ内でデータ取得処理を行わない様に工夫する

で、基本は、上記の流れで良いんじゃぁないかと。


というのが結論なので、どうしてこういう結論になったかは、以下を読んでくださいということで。

あと、最近読んでいる以下の本(かなり面白い)を見て思ったんですけど、

チューニングと一言でいっても色々あるわけでして。

で、今回はタイトルにもある通り、

プログラム(といっても大体SQLのSELECT関連)サイドのチューニングになります。


www.amazon.co.jp


あと、以前に以下の論理削除の記事でも若干触れた、

「マスタデータを何処に持つか」という話も若干絡みますね。


kitoku-magic.hatenablog.com


あと、地味かもしれないですが、

以下の記事もかなり役に立ってます。

というか、この記事見て完全にピンと来たんですけどね。


php-sql-gdgd.jugem.jp


では、「どういう時のボトルネックに対するチューニングなのか」ですが、

「ユーザーIDをキーにして、DBのトランザクションデータからデータを取得(データA)して、その後データAの中のマスタデータのIDをキーにしてマスタデータからデータを取得(データB)する」という様なプログラムです。

勿論、更に続きでデータC・データDと取得したりする事もザラではありますけど。

で、プログラム自体はよくあるプログラムだと思うので、

結構色々な環境で使えるんじゃないかとも思うんですよね。

じゃなきゃ、わざわざ書かないんですけどね(笑)


では、サンプルプログラム(合計9パターン)のご紹介です。

殆ど変わらないのもあるんで、5~6パターンでも良い気もするんですが、折角なので全部。


先にパターンと実行平均時間と高速度順の順位だけ紹介しておきますと、以下の通りです。


【1.トランザクションデータとマスタデータをJOINする】0.0067554741秒(1位)

【2.DBサーバーが別だとJOIN出来ないので、クエリを分ける】0.5855079975秒(8位)

【3.DBサーバーが別だとJOIN出来ないので、クエリを分ける & MySQL複数接続】0.6397109158秒(9位)

【4.マスタをMemcachedにキャッシュする】0.5397023411秒(7位)

【5.マスタをMemcachedにキャッシュする & キャッシュのキーが一つ】0.0144977431秒(2位)

【6.マスタをRedisにキャッシュする & キャッシュのキーが一つ】0.015953728秒(3位)

【7.先にマスタデータを全件取っておく】0.1823107789秒(6位)

【8.マスタデータを事前にAPCに突っ込んでおく】0.122105834秒(4位)

【9.マスタデータを事前にRedisに突っ込んでおく】0.180010453秒(5位)


まずは、DB関連から。


【0.テーブル定義とデータ投入】


// トランザクションデータが入るテーブル
CREATE TABLE `test` (
`user_id` int(11) NOT NULL,
`code` int(11) NOT NULL,
PRIMARY KEY (`user_id`, `code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


// マスタデータが入るテーブル
CREATE TABLE `code_master` (
`code` int(11) NOT NULL,
`name` varchar(100) NOT NULL,
PRIMARY KEY (`code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

// データ投入シェルスクリプト
#!/bin/sh

file_name='insert_code_master.csv'

# マスタテーブルに10万件のデータを投入
for i in `seq 1 100000`
do
  echo "${i},${i}" >> $file_name
done

file_name='insert_test.csv'

# トランザクションテーブルに1億件のデータを投入
for i in `seq 1 100000`
do
  for j in `seq 1 1000`
  do
    echo "${i},${j}" >> $file_name
  done
done


LOAD DATA LOCAL INFILE 'insert_code_master.csv' INTO TABLE code_master FIELDS TERMINATED BY ',' LINES TERMINATED BY '\n';

LOAD DATA LOCAL INFILE 'insert_test.csv' INTO TABLE test FIELDS TERMINATED BY ',' LINES TERMINATED BY '\n';


まず、ここまでです。

ちなみに、以下のインデックスも張ろうかと思いましたが、

結果的に誤差レベルの差で殆ど変わらなかった(今回のクエリではですが)ので、

張ってません。


CREATE INDEX test_code ON test (code);


次に、以下から実際のコードになりますが、

実行方法は以下の様な事をして、EXCELで平均秒を算出しています。


■実行方法
for i in `seq 1 1 1000`; do php {PHPファイル名}.php >> result_{PHPファイル名}.xls; done &


// apcuの時のみ以下
for i in `seq 1 1 1000`; do curl http://localhost/apcu.php >> result_apcu.xls; done &


【1.トランザクションデータとマスタデータをJOINする】

<?php

ini_set('memory_limit', -1);

$conn = new mysqli('DBホスト名', 'ユーザー名', 'パスワード', 'データベース名', 'ポート番号');

if (!$conn) {
    die('データベース接続エラー: ' . mysql_error());
    exit();
}

$user_id = 859;
$start = microtime(true);
$result_array = array();
$sql = 'SELECT cm.name FROM test t LEFT JOIN code_master cm ON t.code = cm.code WHERE t.user_id = ?';
$stmt = $conn->prepare($sql);
$stmt->bind_param('i', $user_id);
$stmt->execute();

$stmt->bind_result($name);

while (true === $stmt->fetch())
{
    //echo $name . "\n";
    $result_array[] = $name;
}

echo microtime(true) - $start . "\n";


1000回平均:0.0067554741秒


う~ん、速い?

というか、他のプログラムと比較しないと分からないので、次に。


【2.DBサーバーが別だとJOIN出来ないので、クエリを分ける】

<?php

ini_set('memory_limit', -1);

$conn = new mysqli('DBホスト名', 'ユーザー名', 'パスワード', 'データベース名', 'ポート番号');

if (!$conn) {
    die('データベース接続エラー: ' . mysql_error());
    exit();
}

$user_id = 859;
$start = microtime(true);
$result_array = array();
$sql = 'SELECT code FROM test WHERE user_id = ?';
$stmt = $conn->prepare($sql);
$stmt->bind_param('i', $user_id);
$stmt->execute();

$stmt->bind_result($code);

$code_array = array();
while (true === $stmt->fetch())
{
    $code_array[] = $code;
}

$stmt->close();
$sql = "SELECT name FROM code_master WHERE code = ?";
$stmt = $conn->prepare($sql);
foreach ($code_array as $code)
{
    //echo $code . "\n";
    $stmt->bind_param('i', $code);
    $stmt->execute();

    $stmt->bind_result($name);

    while (true === $stmt->fetch())
    {
        //echo $name . "\n";
        $result_array[] = $name;
    }
}

echo microtime(true) - $start . "\n";


1000回平均:0.5855079975秒


あら、JOINに比べてだいぶ遅くなりました。

ちなみに遅い原因は、「ループの中でSQL投げてるから」でしょう。

一回一回のSQLは「軽い」と思います(上記だとPKのインデックス効いてますし)けど、

でも「千回も一万回」も投げたら流石にねぇと。


ところが、つい先日までの僕自身の書き方もそうだったんですけど、

こういうプログラム、かなりの現場に潜んでいるんじゃなかろうか?と。

というか、これまでの経験だけでも、結構見覚えが・・・

いや、勿論この速度はデータ量にもよりますし、

そもそも0.6秒が問題にならないシステムなら良いんですけど、

案件によってはね・・・っていう。


ひとまず、次にいきましょう。


【3.DBサーバーが別だとJOIN出来ないので、クエリを分ける & MySQL複数接続】

<?php

ini_set('memory_limit', -1);

$conn = new mysqli('DBホスト名', 'ユーザー名', 'パスワード', 'データベース名', 'ポート番号');

if (!$conn || $conn->connect_errno) {
    die('データベース接続エラー: ' . $conn->connect_error);
    exit();
}

$user_id = 859;
$start = microtime(true);
$result_array = array();
$sql = 'SELECT code FROM test WHERE user_id = ?';
$stmt = $conn->prepare($sql);
$stmt->bind_param('i', $user_id);
$stmt->execute();

$stmt->bind_result($code);

$conn1 = new mysqli('DBホスト名', 'ユーザー名', 'パスワード', 'データベース名', 'ポート番号');
if (!$conn1  || $conn1->connect_errno) {
    die('データベース接続エラー: ' . $conn1->connect_error);
    exit();
}
$sql = "SELECT name FROM code_master WHERE code = ?";
$stmt1 = $conn1->prepare($sql);
while (true === $stmt->fetch())
{
    //echo $code . "\n";
    $stmt1->bind_param('i', $code);
    $stmt1->execute();

    $stmt1->bind_result($name);

    while (true === $stmt1->fetch())
    {
        //echo $name . "\n";
        $result_array[] = $name;
    }
}

echo microtime(true) - $start . "\n";


1000回平均:0.6397109158秒


こちらは、2番のプログラムの中の「$code_array」配列に要素を突っ込むのと、

その後に、$code_array配列内の要素を一つずつ取り出す部分の、

「繰り返し処理を一つにまとめた」パターンなんですが、

1ユーザーでDB接続数2以上って事で、逆に遅くなってますかね。

どっちにしても、1ユーザーでDB接続数2以上って時点で速くてもイヤですけど。

ちなみに、繰り返し処理を一つにまとめる他の方法として、

2番のプログラムの最初の$stmt->fetch()辺りの箇所を、

$stmt->get_result()とすれば、また同じ$stmt変数使えて繰り返し処理も一つに出来ます。

ただ、それをしても大体「0.59秒」ぐらいということで、特に変化無かったですね。

では、次。


【4.マスタをMemcachedにキャッシュする】

<?php

ini_set('memory_limit', -1);

$conn = new mysqli('DBホスト名', 'ユーザー名', 'パスワード', 'データベース名', 'ポート番号');

if (!$conn) {
    die('データベース接続エラー: ' . mysql_error());
    exit();
}

$user_id = 859;
$start = microtime(true);
$result_array = array();
$sql = 'SELECT code FROM test WHERE user_id = ?';
$stmt = $conn->prepare($sql);
$stmt->bind_param('i', $user_id);
$stmt->execute();

$stmt->bind_result($code);

$code_array = array();
while (true === $stmt->fetch())
{
    $code_array[] = $code;
}

$stmt->close();
$sql = "SELECT name FROM code_master WHERE code = ?";

$memcached = new Memcached();
$memcached->addServer('Memcachedホスト名', ポート番号);

foreach ($code_array as $code)
{
    //echo $code . "\n";
    $cache_key = $user_id . '_' . $code;
    $name = $memcached->get($cache_key);
    if (false === $name)
    {
        $stmt = $conn->prepare($sql);
        $stmt->bind_param('i', $code);
        $stmt->execute();

        $stmt->bind_result($name);

        while (true === $stmt->fetch())
        {
            //echo '$name1:' . $name . "\n";
            $result_array[] = $name;
            $memcached->set($cache_key, $name);
        }
    }
    else
    {
        //echo '$name2:' . $name . "\n";
        $result_array[] = $name;
    }
}

echo microtime(true) - $start . "\n";


1000回平均:0.5397023411秒


おお、流石Memcachedと言いたい所ですけど、

でも、それでも「JOINより遅い」んですよね。

・・・ふと思ったんですけど、

これ「ネットワークの通信(あるいは回線?)速度(あるいは回数?)」も、結構影響大きいのでは?(今回、Web・DB・KVS全てが別サーバ)とも思いますね。

いや、今回その辺までは調べてませんけど。

ひとまず、次に。


【5.マスタをMemcachedにキャッシュする & キャッシュのキーが一つ】

<?php

ini_set('memory_limit', -1);

$conn = new mysqli('DBホスト名', 'ユーザー名', 'パスワード', 'データベース名', 'ポート番号');

if (!$conn) {
    die('データベース接続エラー: ' . mysql_error());
    exit();
}

$user_id = 859;
$start = microtime(true);
$result_array = array();
$sql = 'SELECT code FROM test WHERE user_id = ?';
$stmt = $conn->prepare($sql);
$stmt->bind_param('i', $user_id);
$stmt->execute();

$stmt->bind_result($code);

$code_array = array();
while (true === $stmt->fetch())
{
    $code_array[] = $code;
}

$stmt->close();
$sql = "SELECT name FROM code_master WHERE code = ?";

$memcached = new Memcached();
$memcached->addServer('Memcachedホスト名', ポート番号);
$cache_key = 'code_master' . '_' . $user_id;
$name_array = array();
$result = $memcached->get($cache_key);

foreach ($code_array as $code)
{
    //echo $code . "\n";
    if (false === $result || false === isset($result[$code]))
    {
        $stmt = $conn->prepare($sql);
        $stmt->bind_param('i', $code);
        $stmt->execute();

        $stmt->bind_result($name);

        while (true === $stmt->fetch())
        {
            //echo '$name1:' . $name . "\n";
            $name_array[$code] = $name;
            $result_array[] = $name;
        }
    }
    else
    {
        //echo '$name2:' . $name . "\n";
        $name_array[$code] = $result[$code];
        $result_array[] = $result[$code];
    }
}
if (0 < count($name_array))
{
    $memcached->set($cache_key, $name_array);
}

echo microtime(true) - $start . "\n";


1000回平均:0.0144977431秒


あら~なんと、これはJOINとほぼ同じですね。

ただ、このプログラムの問題は「メモリ食う」ですね。

・・・あ、これ、$resultと$name_arrayは変数を一つにまとめても問題無さそうですね。

これを書いている途中で気付きました(苦笑)

ということで、まだ速くなりそうですし、別にメモリもさほど食わないかも(苦笑)

あと、ついでにもう一つ書いてる途中に気付いた事として、

ループ内で「$stmt = $conn->prepare($sql);」と書いてある場合は、

大抵はループ外に出せますね(元々が「準備された文」だから当然か)。

ひとまず、次行きましょう。


【6.マスタをRedisにキャッシュする & キャッシュのキーが一つ】

<?php

ini_set('memory_limit', -1);

$conn = new mysqli('DBホスト名', 'ユーザー名', 'パスワード', 'データベース名', 'ポート番号');

if (!$conn) {
    die('データベース接続エラー: ' . mysql_error());
    exit();
}

$user_id = 859;
$start = microtime(true);
$result_array = array();
$sql = 'SELECT code FROM test WHERE user_id = ?';
$stmt = $conn->prepare($sql);
$stmt->bind_param('i', $user_id);
$stmt->execute();

$stmt->bind_result($code);

$code_array = array();
while (true === $stmt->fetch())
{
    $code_array[] = $code;
}

$stmt->close();
$sql = "SELECT name FROM code_master WHERE code = ?";

$name_array = array();
$redis = new Redis();
$redis->connect('Redisホスト名', ポート番号);
$cache_key = 'code_master' . '_' . $user_id;
$result = $redis->get($cache_key);
if (false !== $result)
{
    $result = json_decode($result, true);
}

foreach ($code_array as $code)
{
    //echo $code . "\n";
    if (false === $result || false === isset($result[$code]))
    {
        $stmt = $conn->prepare($sql);
        $stmt->bind_param('i', $code);
        $stmt->execute();

        $stmt->bind_result($name);

        while (true === $stmt->fetch())
        {
            //echo '$name1:' . $name . "\n";
            $name_array[$code] = $name;
            $result_array[] = $name;
        }
    }
    else
    {
        //echo '$name2:' . $name . "\n";
        $name_array[$code] = $result[$code];
        $result_array[] = $result[$code];
    }
}
if (0 < count($name_array))
{
    $redis->set($cache_key, json_encode($name_array));
}

echo microtime(true) - $start . "\n";


1000回平均:0.015953728秒


Memcachedと殆ど同じという事で。

ただ、こっちはjson_encode & decode(Redisの他のデータ型なら不要かもしれないですけど)の分、

処理がメンドイと。

っていうのもあるし、Redisは無駄に多機能な事を考えても、

今回の様な用途なら、Memcachedの方が良いのではとは思いますね。

次。


【7.先にマスタデータを全件取っておく】

<?php

ini_set('memory_limit', -1);

$conn = new mysqli('DBホスト名', 'ユーザー名', 'パスワード', 'データベース名', 'ポート番号');

if (!$conn) {
    die('データベース接続エラー: ' . mysql_error());
    exit();
}

$user_id = 859;
$start = microtime(true);
$result_array = array();
$sql = 'SELECT code FROM test WHERE user_id = ?';
$stmt = $conn->prepare($sql);
$stmt->bind_param('i', $user_id);
$stmt->execute();

$stmt->bind_result($code);

$code_array = array();
while (true === $stmt->fetch())
{
    $code_array[$code] = $code;
}

$stmt->close();

$redis = new Redis();
$redis->connect('Redisホスト名', ポート番号);

$redis_key = 'code_master' . '_' . $user_id;

$all_master_data = $redis->get($redis_key);
if (false === $all_master_data)
{
    $all_master_data = array();
    $sql = "SELECT code, name FROM code_master";
    $stmt = $conn->prepare($sql);
    $stmt->execute();

    $stmt->bind_result($code, $name);

    while (true === $stmt->fetch())
    {
        $all_master_data[$code] = $name;
    }
    if (0 < count($all_master_data))
    {
        $redis->set($redis_key, json_encode($all_master_data));
    }
}
else
{
    // json_decodeは、第二引数をtrueにすると連想配列形式のデータを返す(デフォルトはstd_class)
    $all_master_data = json_decode($all_master_data, true);
}

foreach ($code_array as $code)
{
    // もし、ここで、$all_master_data[$code]にデータが無かったら、マスタに無いコードがtestテーブルに入ってる
    $result_array[] = $all_master_data[$code];
}

echo microtime(true) - $start . "\n";


1000回平均:0.1823107789秒


さて、こちらは前述の通り「ループ内でSQLを投げる」のが遅いということなので、

「ループ外でSQL1回投げて全件取って、ループ内でSQLは投げない様にする」という改良を入れたプログラムです。

で、上記の平均はRedisのキャッシュ効いている状態の平均ですが、

このプログラムをRedisだけ使わない様に修正しても、「0.35秒ぐらい」ということで、

以下の3つがAND条件で全てYesの場合には、

今回のパターン内では一番速い(ただ、マスタ全件を配列に格納するので、メモリ不足には注意)ですね。


・JOIN出来ない

・KVSも無い

・後述のAPCも無い


ということで、まぁまぁオススメかと。

では、次。


【8.マスタデータを事前にAPCに突っ込んでおく】

<?php

ini_set('memory_limit', -1);

$conn = new mysqli('DBホスト名', 'ユーザー名', 'パスワード', 'データベース名', 'ポート番号');

if (!$conn) {
    die('データベース接続エラー: ' . mysql_error());
    exit();
}

$user_id = 859;
$apc_key = 'code_master' . '_' . $user_id;

$all_master_data = apc_fetch($apc_key, $success);
if (false === $all_master_data || false === $success)
{
    $all_master_data = array();
    $sql = "SELECT code, name FROM code_master";
    $stmt = $conn->prepare($sql);
    $stmt->execute();

    $stmt->bind_result($code, $name);

    while (true === $stmt->fetch())
    {
        $all_master_data[$code] = $name;
    }
    if (0 < count($all_master_data))
    {
        apc_store($apc_key, $all_master_data);
    }
    $stmt->close();
}

$start = microtime(true);
$result_array = array();
$sql = 'SELECT code FROM test WHERE user_id = ?';
$stmt = $conn->prepare($sql);
$stmt->bind_param('i', $user_id);
$stmt->execute();

$stmt->bind_result($code);

while (true === $stmt->fetch())
{
    $result_array[] = $all_master_data[$code];
}

echo microtime(true) - $start . "\n";


1000回平均:0.122105834秒


まず、このプログラムのマスタから「事前に」って言ってる所についての補足ですが、

「事前に」っていうのは、この「個別」処理を行う前の「共通」処理で事前に行うって意味です。

なので、このプログラムは、「$start = microtime(true);」の位置が途中からになっています。

その点、ご注意を。

で、まぁ、速度的に悪くはないわけですけど、

「マスタ全件をキャッシュ」よりは、

「存在したマスタのID分のデータだけキャッシュ」の方が当然、効率は良いですよね。

ただ、このプログラム「だけ」ならそうなんですけど、「全体」で見た場合にはどうかなと。

「共有可能なデータ」は、共有した方が良いでしょうし。

まぁ、共有したけど使われない処理が殆どだったってケースも考えられるので、「共有するデータの選定」がポイントでしょうけど。

あと、APCに関しては、チラっとしか見てないですけど、

キャッシュがクリアされないだの何だのといったトラブル事例(回避策も同時に載っていた記憶もかすかにあるが)もチラホラ見かけましたので、

まぁ、あんまりじゃあないかという気もしますね。

あと、APCってWebサーバ毎にキャッシュ持つと思うんですけど、

そうすると、キャッシュのヒット率は低いのではってのもありますかね?

なので、特に理由無ければMemcachedなどの方が良いかなぁと。

じゃあ、次で最後です。


【9.マスタデータを事前にRedisに突っ込んでおく】

<?php

ini_set('memory_limit', -1);

$conn = new mysqli('DBホスト名', 'ユーザー名', 'パスワード', 'データベース名', 'ポート番号');

if (!$conn) {
    die('データベース接続エラー: ' . mysql_error());
    exit();
}

$user_id = 859;
$start = microtime(true);

$redis = new Redis();
$redis->connect('Redisホスト名', ポート番号);
$cache_key = 'code_master' . '_' . $user_id;

$all_master_data = $redis->get($cache_key);
if (false === $all_master_data)
{
    $all_master_data = array();
    $sql = "SELECT code, name FROM code_master";
    $stmt = $conn->prepare($sql);
    $stmt->execute();

    $stmt->bind_result($code, $name);

    while (true === $stmt->fetch())
    {
        $all_master_data[$code] = $name;
    }
    if (0 < count($all_master_data))
    {
        $redis->set($cache_key, json_encode($all_master_data));
    }
    $stmt->close();
}
else
{
    $all_master_data = json_decode($all_master_data, true);
}

$result_array = array();
$sql = 'SELECT code FROM test WHERE user_id = ?';
$stmt = $conn->prepare($sql);
$stmt->bind_param('i', $user_id);
$stmt->execute();

$stmt->bind_result($code);

while (true === $stmt->fetch())
{
    $result_array[] = $all_master_data[$code];
}

echo microtime(true) - $start . "\n";


1000回平均:0.180010453秒


APCをRedisに変えただけなので特に。

Redisの方が遅いのは意外でしたけど。

ということで、結論に。


【結論】


1.JOINが出来るなら、まずはJOINを検討。あと、OFFSETとLIMITが使えるなら、よりベター。

2.JOINが出来ないなら、NoSQLを上手く使う。その際、出来るだけループ内でデータ取得処理を行わない様に工夫する

基本は、上記の流れで良いんじゃぁないかと。

あと、とにかく重要なのが、「ループ内でデータ取得(SQLも、NoSQLのget()も)を出来るだけ控えろ」という点。

更に、画面設計的にページング(スマホだとスクロールが同義語?)処理にするとかも大事ですね、って基本ですけど。


あと最後に、チューニングにおける「鉄則中の鉄則」ですけど、

「推測するな、計測せよ」ってのは、

「JOINが遅いのも、ケースバイケース」ということからも感じた所ですので、

胸に刻み込んで、日々の業務に携わるのが良いんじゃないかと思いましたね。


いつもの事ですが、何かご意見やご感想などありましたら、遠慮無くいただければと思います。

性犯罪をしにくくしつつ性欲を満たすビジネスモデルの草案

相当に厄介なテーマなんですけどね。

ただ、考えてみたら、結構昔から時々書いているネタでもあるので。

 

まず、情報提供を希望したいんですけど、「国内・国外問わず、性犯罪率を低下させる目的のWebサービス(サービス名やトップのURL)」の情報提供を希望します。

僕が思い付いたぐらいですから、既にある様に思うんですよね、だから。

で、これを書いた理由は、最後まで読むと分かると思いますけどね。

だから最後にもまた書きますけど。

 

では、本題に入ります。

あと、今回は草案なのでざっくり(それでも長いけど)です。

 

まず、インターネットの特徴を考えてみますと、

「情報の公開範囲(制限しなければ全世界に公開)」

「情報と情報の繋ぎ合わせが容易(リンク機能)」

アーカイブ(情報の保持)性が高い(消されなければずっと残る)」

というものがあると思います。

いや、これで全部だとは思いませんけど。

 

で、プラスの側面からいきますと、

「美味しい料理の作り方」とか、

「ヒーリングに良い音楽」とか、

システム開発における、開発ノウハウ」とか、

おそらく真剣に書きだしたらとんでもない量になると思いますけど、

そういった「知識や、良いノウハウの共有と永続性」があると思います。

 

ただ、逆に困る(相性が悪いともいう)のが、今回のテーマの様な時。

例えば、以下の様なケース。

「リアルでミニスカートを履いていてたまたま転んだ結果、パンツが見えた状況を盗撮されネットの画像・動画サイトにアップロードされて、ずっとそのまま」

「被害の当事者的には、その時は気付かなかったが、あとになって気付く」

といった被害報告的なページも、多々存在しています。

 

で、こういった現状に対して、「忘れられる権利」とか「ペチパンツを開発」とか「シャッター音が鳴るカメラ」とか、色々な業界が色々な手法を用いて解決策を見出そうとしていますけど、データ的には以下の様な状況の様です。

 

matome.naver.jp

 

上記ページ内の以下のリンクにもある様に、

「犯罪件数」自体は減ってるんですけどね。

なので、「内訳」が問題と。

 

www.hazardlab.jp

 

増えた原因は、まぁスマホのカメラはあるんでしょうけど、

正直この辺は「使い方の問題」でしょうと。

個人的には、仙台とか伊豆とか大阪とかに旅行に行った時の写真がありましたね。

夜景とか色々ありますけど。

 

他に考えられる事として、まぁ一杯あると思いますけど、

個人的に取り上げたいのは、「即効性」と「遅効性」の話(この記事の元ネタになった)ですね。

 

www.asahi.com

 

結構、ここら辺は印象度が強いんですけど、

ヌード(全裸)は、ストレートで即効性は高いんでしょうけどね。

でも、「深みが無いので飽き易い」。

パンチラとパンモロ(こっちの方が深みが無い)も一緒。

あと、上記はログインしないと見れないので、以下も貼っておきます。

 

toyokeizai.net

 

「今ではクリックひとつで想像の及ぶあらゆる性行為がタダで見られる。そんな時代に(ヌード写真は)時代遅れだ」

 

ここは意見が違います(今回の記事と対立してますし)けど、

単純な性欲解消にあまり興味が無いので、ヌードを失くすという大枠の方向性自体は賛成ですね。

なので、まずは、この「深み」の存在があります。

 

それと、女性側からの観点として、

上記のペチパンツもそうですけど、

性犯罪防止観点(だとしか思えないが)から、

下着が進化していると。

これは、歴史を見ると早いですね。

 

www.cocoros.jp

 

いや、勿論下着に限らず、

スポーツ着メーカー(ブルマとかね)とか、

学校側の取り組み(体操着の選定とかね)とか、

AV(これは否定的な意見もありそうですが)とか、

色々な取り組みがされているわけですけど、

性犯罪は全く無くならない(むしろ上記の通り増えている)。

・・・商品の進化に、人間(この場合、男ですけど)が追い付いていない感がありますね。

ちなみにココ、セキュリティ業界でよく言われる「イタチごっこ」と、構図が全く一緒かと。

「男性が攻撃側」で、「女性が防御側」という意味で。

なので、ピンときた方はご存知の通り、この話「人類が滅亡しない限り、永久に終わらない」と予想しています。

ということで、商品は「深み」に対応してはいるので、

人間も深みに対応しなければいけないのではないかというのも、ポイントかと。

・・・一番、妥当な手段はAVなんですけどね。

一番簡単だと思いますし。

ただ、AVで済まない人向けには、

深みに対応する必要があるかなと。

 

で、この「深みに対応」するのに必要な能力として、

「妄想力」を磨く必要がありまして。

 

例えば、上記のペチパンツを題材にしましょう。

以下の様なもの(確かに最近ちょくちょく見かけますね)です。

 

www.peachjohn.co.jp

 

で、例えばリアルで、この服装の女性を「襲わず盗撮せず何もせずに(言うまでもない)」、どうやって性欲を解消するのか?

 

ポイントは、言葉(文章や声)と心理(羞恥心)。

え、キモい・・・それは最後のQ&Aをご覧下さい。

・・・この分野、「綺麗な解決策」の実践だけでの解決って難しそうなんですよね(苦笑)

 

話を戻しまして、言葉と心理について。

まず、「何故、この人はペチパンツを履いているのか?」という「心理(動機といった方が良いかも?)」を予測します。

どうやって予測するかは、上記のページなどの「口コミ」とか。

で、簡単な予測結果としては、パンチラ防止(他にもあると思うけど、今回は省略)を目的としていると。

 

で、ここからが「妄想(頭の中だけ。手や体は勿論動かない)」です。

・・・人によって全然違うでしょうし、何パターンも思い付くし何とも言えないですけど、例えば以下。

「ズボンじゃなくてスカートが好きなのか?で、スカートが好きってことは、お尻が大きいから隠したいのか?でも、スカートだと今度はパンチラが怖いので、ペチパンツを履いてパンチラ防止と。じゃあ、ペチパンツを履いてまで隠したいパンツは、どんなパンツだろう?{自分の好みのパンツのデザイン}に違いない!じゃあ、なんで{自分の好みのパンツのデザイン}を履いているかというと・・・キリが無いので省略」

・・・途中で噴いてしまいましたね(苦笑)

ただ、基本的にはこういう様なアプローチを取って、「口コミを書いた人(大体のケースにおいて、何も知らない人のはず)」と「対象者(奥様でも、今好きな人でも、過去に好きだった人でも)をイメージ」して「結び付けて、その人がこの口コミを書いた事にして」、「前述の妄想に更に妄想を重ねて興奮度がどんどんどんどん上がってMAXになった所」で、「マスターベーション」して終了です。とんでもない(苦笑)

ちなみに、結び付けに関しては、知ってる人ほど「アイツは、こんな口コミ書かないな」となって結び付けしにくい(どっかで無理が出る)ので、どっちかというと「知らない人」をお勧めします。だから、通りすがりの{自分の好みの見た目の女性}が一番良いですね。・・・いやでも、ちょっと知ってるぐらいの人の時もありますね。ただ、少なくとも、「知ってる度合いが高ければ高いほど、妄想展開に無理が出てきやすいので、除外されやすい」のは確かですね。

 

で、ビジネス的には、この辺が題材です。

つまり、「色々な質問によって、現在のエロ妄想力を診断して、診断結果に応じて妄想力を磨いて、マスターベーションを行い性欲を解消(よって遅漏解消などにも)し、性犯罪に向かう衝動を抑える」という「Webサービス(ただし、オフラインも絡むと思われます)」。

で、こういうの無いんですか?というのが、一番最初の「情報提供」の話です。

あと、マスターベーションは、やり過ぎはダメでしょうけど、以下の様な健康効果もある様ですね。やっぱり(笑)

 

spotlight-media.jp

 

あと、上記の質問内容はどういうものかについて、色々用意はある(といっても数がまだ足りなさそう)んですけど、例えば以下の様な感じです。あと、おそらくは複数回答のものが多くなる気もします。

 

Q1.知り合い(奥様・恋人・友達など)の下着のデザインに、あなたは意見を挟みますか?

 

1.本人の勝手にすれば良いので、一切口を挟まない

2.女性側が希望したなら、意見を挟む

3.女性側の希望の有無に関係なく、意見を挟む

4.意見を挟みつつ、女性用の下着売り場に同行する

5.・・・夢が叶った。女性用の下着売り場に行って・・・以下省略(苦笑)

 

Q2.ミニスカートを履いておきながら、パンチラ防止に努める女性について、あなたはどう思いますか?

 

1.どうせブスでしょ?そうじゃなくても自意識過剰過ぎだし、ミニスカ履いてるなら、パンチラは諦めろよ

2.大切な部分を守るという乙女心について考えていると思うので、好感が持てる

3.マナーとして普通だと思う

4.何か過去に辛い体験あったのかなと想像し、可愛そうに思う

5.上記のペチパンツの妄想と同じ(苦笑)

 

Q3.最近、Twitterのデザインで、★マークから♥マークに変わった所がありますが、あなたはどう思いますか?

 

1.改悪である

2.相手がどう解釈しようが、特に使い方を変える気もないので、何も気にしない

3.Twitter婚増加間違いなし!

4.草食系の男女が、過度に意識し過ぎて、利用度合いが減りそう

5.本当は♥マークを押したいのに、愛情表現と勘違いされそうで恥ずかしいから押さない女性とかクッソ可愛いわ!

 

・・・今回は、「・・・」の多い記事になってますが、

「・・・」の箇所の大半は、アンフェアの雪平夏見の「バカかお前は」に置き換えておいて下さい(苦笑)

いやでも、「多角的」に質問しないと、診断って難しいのではと思いますんで。

ちなみに、一見安全そうな「1~2辺りの回答」でも、例えば本音を語らない様な人(プライドや社会的立場とかから)なら、そう安心でもないと思いますね。勿論、1~2でも全く問題ない(多分、ここが大多数?)人もいらっしゃるでしょうし、4~5だから危ないともいえない(この話は、倫理観が最大のポイント)わけですので、結構難しいです。

 

で、診断結果(ここまでは無料)出ました。で、その後の性欲解消コース?が「有料」です。で、ここは「オンライン(難しいぞコレ)・オフライン」併用な感じです。先程書いた様な手法(他にも色々とあるわけですけど。といってもこっちも数が足り無さそう)によって、個別に解決策を考えていきましょうと。カウンセリングっぽいですね。

ここは、値段高くなりそうなので、何種類かコース(簡単なものや本格的なもの)を用意した方が良さそうですね。

 

あと、個人的に思っているポイントとしては、以下かなと。

 

1.ネットの特徴(一番最初に書いた話)を考えると、エロは大変に相性が悪い(拡散しやすいし、永久に残る)ので、Webサービスを使って、この辺のおとしまえを付けられないか

 

2.ネット上の画像と動画(勿論、本人の同意が無いもの)に頼らず(AVで解決するなら、それが一番穏当かと)、テキストなどからの妄想力アップによって、性欲不満を解消する

 

3.上記の1番抜きにしても、マスターベーションからの健康対策に良いのでは?

 

ひとまず、「草案」としてはこんな所です。

最後にQ&Aで締めます。

 

 

1.AVとか風俗とかパンツゲーとかがあるから、性犯罪が増えるので、即刻全て失くすべき

 

さすがに今時・・・とは思いますけど、仮に法令などでそうなったら「この国出ていきましょうか」。

「本格的なディストピア突入間違いなし」でしょうけど、逆に言うと今はまだなっていない(と思うが)ので、「言われている程、悪い国(別に、全てが良い国とも言いませんけど)」では無いと思いますね。

 

2.言葉から好き勝手に妄想して女性の心理を読むとか、あり得ないしキモ過ぎる。そもそも、男性がスケベな事を考えなければ良いし。あと誰も言葉を言わなくなったり、口コミを書かなくなるよ?

 

「男性がスケベな事を考えなければ良い」は、上記1と本質一緒。「性欲のコントロールの問題」でしか無いので。あと、「誰も言葉を言わなくなったり、口コミを書かなくなる」については、じゃあ「言わなくなったり書かなくなった原因を予測する」となる(だから、セキュリティのイタチごっこと一緒)だけですね。あと、別に「ネットのテキストに限定していない」ですし。

と言いますか、以下のどっちが「まだマシ」だと思います?

 

(1)リアルで盗撮されて、知らない間にネットにアップされて拡散されて、それを見た人とリアルでバッタリ会って教えられた(或いは、そのまま性犯罪に巻き込まれた)が、既に削除申請も間に合わず、何処かで永遠に残る。対象は、自分の場合もあれば、自分の子供の場合もある

 

(2)リアルでもネットでも何の接点もない人が、自分の全く知らない所で勝手に妄想して性欲を解消しているが、犯罪に巻き込まれることはない

 

で、僕が推奨しているのは(2)の方で、要するに(1)に対する対策ですね。

綺麗にいくなら、「適切な性教育」「他人が嫌がっている(ちなみに、ストックホルム症候群を考えると、嫌がっていなくても微妙)のにやるな」とかでしょうけど、それが出来ているなら苦労しないですね。

 

で、コレ、いじめと同じで「やる方が悪い」んです。だから、それ(今回の場合は性欲)をコントロールする為に、妄想力を鍛える(じゃなくて、普通の治療とかでも良いんですけど)という話なんです。

 

「妄想力とかキモイ」のは間違いないでしょうし、綺麗な対策が「全」国民に行き届くのが一番良いわけですけど、上記の統計データの通りなわけで、そこは我慢出来ないものですかね。この点は、仮にネットが無くなっても変わらないと思いますし。

 

3.女性に配慮し過ぎでは無いか?

 

まぁ、以下みたいなのもあるみたいですし。いわゆる、「リベンジポルノ」ってやつ(僕は、オヤジ狩りを思い出しましたけど)ですかね。リベンジポルノは、男性が女性に対してってイメージ強いかもしれないですけど、以下の通り、逆だって有り得るでしょうし。

 

girlschannel.net

 

4.ビジネスチックに語っているけど、そもそもは卑猥な動機ですよね?

 

「卑猥」が何を指し示すかによる様な。性欲解消が「卑猥」ですかね。

あと、ビジネスって、いわゆる社会的責任(CSR)を持って社会的問題解決や社会の発展に繋げるって事だと思いますし、じゃあAV製造メーカーや風俗もNGになりませんかね。

 

5.ブラとか、上半身の話が全然無いような?

 

ココ悩ましい問題で。上半身は「全然」興味が無いものでしてね。もし、やるなら本格的に勉強はしてみますけど。

 

6.倫理(ここでは、やってはいけない事という意味合い)の問題が一番大きいし、根っ子なのでは?

 

ええ、全くその通りかと。「女性は好きじゃないのか?」「好きな相手が嫌がっているのに、どうしてやるのか?」ってのが、個人的に「サッパリ」分からないんですけどね。

 

「女性に騙されたから」は、すいません僕も昔キャバクラで騙された(わけじゃないが、貢ぎまくった(苦笑))けど、「良い社会勉強(それにしても、高い出費でしたが)だったかなぁ」と。

「女性が自分に全く相手してくれないから」は、それは貴方にも何がしかの問題があるんじゃないでしょうかね。僕が言っても、ちっとも説得力無いでしょうけど(苦笑)

 

7.性欲を満たすだけで、性犯罪は起こさなくなるのか?

 

多分、上記6の倫理が根っ子と思われるので、完全には微妙。でも、減るとは思うんですけど、どうでしょうかね。要分析かと。

 

8.難易度高過ぎないか?

 

上記のペチパンツはまぁ確かに。

AVの、中の女優を「自分の好きな人」に置き換えるのが、一番簡単かなと思いますね。

 

9.リアルではちょっとした発言だけでもセクハラ扱いされる時もあるが、ネットでは大丈夫なのか?

 

この記事もそうですけど、「女性に対して直接言わなければ良い」のでは。被害妄想強過ぎる女性(といっても、コレも元の原因は男にあったりもするみたいですし。全部ではないでしょうけど)だと、ちょっと厄介でしょうけど。実際、直接話したケースって、相当昔に女性がエロ(というより恋愛だった気がするが)ネタにノッテきた時に、話したぐらいですし。

 

10.逆に、kitoku_magic的に、性欲解消が困難なケースってどういうケース?

 

きっついのだと、「ロボット的対応(感情表現を一切出さない)」。

つまり、この記事に対して「何の反応もしない」がベストですね、女性から見れば。一方で、反応しなければ(男だけの問題じゃないので)問題解決に繋がりにくくもなるんですけど。・・・まぁ、「女性とバレなければ良い」んですけどね。

ただ、仮に全ての女性がロボット的対応をしたとしても、「過去の記憶」が無くならない以上は、「思い出の青春時代」とか使えば良いんじゃないでしょうか(苦笑)

 

11.どうして、kitoku_magicは、こんな風になっちゃったの?

 

・・・・・・・・・・・・・・・分かりません(苦笑)

ただ、合法の範囲内で性欲解消を「継続的に」するのに、相当に苦しんだ人間が編み出した手法ではあるんでしょうけどね。

 

まだまだまだまだまだ話はありますが、一旦締めます。

あと、一番最初に書いた件ですが、「国内・国外問わず、性犯罪率を低下させる目的のWebサービス(サービス名やトップのURL)」の情報提供を希望します。

 

案件の状況とか排他制御とか色々

えっと、久々にITシステム関連の現状について色々書くことにします。

まず、主に先月観察していた案件状況から。

 

1.言語間での単価の違い

 

まだ観察が少ない気もするんですけど、

やっぱり結構この辺もあるのかなと。

具体的には、RubyPythonが高いケースが多く、

PHPPerlPerlは殆ど見ていないが)が低いケースが多い印象です。

CとかC++とかJavaは全然見ていないので分からないですけど。

あと、GoやErlangも数が少ないので分からないですね。

 

予想では、開発者の「数」が影響しているんだろうと思いますね。

勿論、数が少なくても需要が無いとダメではありますけど。

あと、言語毎の特徴(出来る事)や性能(速度)は、

そんなに重要視されてはいない様にも感じますね。

だったら、CやC++Javaがもう少しWebで使われても良いでしょうから。

 

RubyPythonならなぁ・・・個人的にはPythonの方が好みかな。

全然と言っていい程知らないですけど、

言語にコーディング規約が存在するっていうのは気に入りましたしね。

と言いつつ、PHPでも月70万ぐらいだったらあったりもしたので、

取引先次第な部分も多いとは思いますけどね。

 

2・準委任VS請負

 

結構前からボンヤリとは思ってはいたんですけどね、この辺は。

まず、基本的には以下の様な傾向があると思っています。

 

1.発注者はシステムの完成まで面倒見て欲しいので請負を好む

2.ただ、システム開発の場合、システムを完成して納品という形態が馴染まない部分も多く、準委任などの成果物を問わない形態の契約の方が相性が良かったりもする

3.金額的には、請負の方が高い場合が多いが、見積もり次第な部分もある

 

まぁ、相性悪い部分があるにしても、

それでも発注側としては作り切ってからお金を払いたいというニーズは間違いなくあるでしょうから、

ポイントなのはやっぱり「成果物の定義」という事になってはくるだろうと思うんですけど、ココが揉める所ですしねぇ(苦笑)

まぁ、「要件」って基本的に難しいとは思うんですけどね。

個人的には、「こんな家に住みたい」「こんなゲームがしたい」「こんな人と結婚したい」「こんな人生を送りたい」とかを考えるのと、システム開発の要件を考えるのって、「自分の希望を整理する」って意味で似ていると思ってまして、で、前述の難しさを考えてみても難しいだろうなぁと思いますし。

 

ということもあり?最近は、設計や運用以外の開発工程でも、準委任の契約案件が増えている?し、そういうエンジニア(これは実際に何人か見た)も増えている印象ですね。でも、金額は安くなりがちと。

 

金額に関しては、以下のツイートをした事があるんですけど、

この辺は、「国の景気」や「業界の景気」も関係してくるのかなとも思いますね。

リーマンショックの時に案件激減したのを見ても。

 

kitoku_magic on Twitter: "@tyonekura 「平均」(なので一概には言えない)だと、確かにそのぐらいな気もしますね。あと、個人的には、日本は「上限」が低い(1500万以上とかになると、かなり厳しい)印象の方もありますね。"

 

だから、ビジネスに関して成功して欲しいというのは常々あるんですけど、

現状見てると、「短期的な視点"しか"ない」のと、

「一つのサービスに対する期待値が高過ぎる」が殆どなんですよね。

特に、最近後者に関してよく思うんですけど、

「そのサービス、もう伸びしろあんまり無いと思うよ」って思うサービスなのに、

「まだまだ売り上げ上げるんだ!」というノリで過剰に働き続けたにも関わらず、

思うような結果が出ないということで、モチベもダウンしていくという。

多分、こういう時にポイントなのは、

勿論売り上げを維持するっていうのは大事なんですけど、

どっかのタイミングで「損切り」をすることなんだろうと思いますね。

で、この辺が上手なのが経営上手なんでしょうと、きっと。

 

この辺、引き続き見ていきますけど、とりあえず現状ではこんな印象ですね。

 

3.直接契約

 

結局、契約には至らなかったものの、

エンジニアを企業と結びつける会社であるにも関わらず、

契約は、エンジニアと企業が直接行うというケースがありまして。

まぁ、この人材紹介サービスというか、

この商売形態もそんなに稼げる商売ではないと思いますし、

確かにそんなに労力を割く必要も無い気はしますね。

実際、上記の会社も、他の事業も合わせてやって稼いでいるとの事でしたから。

 

4.GitHub釣り

 

どうやら、一部のスタートアップ企業とか、

あと、ちょっと前から大企業も追随し始めているみたいですけど、

採用方面において、GitHubの重要度がかなり高くなっている様で。

 

ただ、ココは結構以前から、

職務経歴書とか、短い面談時間だけじゃ判断難しい」と思ってはいましたし、

上記のGitHubと類似と思われる「面談時に技術の問題のクイズを解く」というのにも、

基本的に賛成だったので、良い傾向だとは思いますけどね。

ただ、GitHubだと海外のエンジニアも対象になるので、

そこが厄介ではあるんですけど。

 

過剰にセルフブランディングとか意識せよとまでは思わないですけど、

とはいえ、Webで何にもやっていないのは、

裏で色々やっていたとしても、相手から認識してもらうのが難しいので、

特に、WebのエンジニアならWebを活用せよとは思いますかね。

 

「Webに何かを公開する」って観点って、個人的には

「書店に行った時に、Webの未購入の本の一覧を見て、どれを買うか考える」とか、

「自分のPC以外で仕事する時に、Webのvimrcの内容をコピーしてくる」とか、

色々便利なんですけどね(笑)

あと、まだ殆どやっていないですけど、

考察系記事の内容を、仕事中に他の人に見せたりも出来ますし。

 

ということで個人的には、

もっとWebを(リアルもだが)有効活用していきたいと思った次第でした。

 

5.サーフィンはこんな所にも効果が

 

比較的成功しているスタートアップ経営者の話を聞く機会があったんですけど、

どうやら、サービスを立ち上げる時に、

日本は勿論、海外の競合事例などを"あり得ないぐらい"沢山調べているとの事で、

「あぁ、情報収集のサーフィンが半端ないんだな」と。

あと、技術系のイベントのLTを聞いていて、

「あぁ、皆さん技術で"遊んで"モチベ管理しているのか」と思ったりとか。

特に、後者については、

僕は最近技術で遊ぶという観点が薄れてきていたので、

だいぶん参考になりましたね。

 

6.排他制御について

 

時々書いている、「NoSQLでトランザクション管理」の話なんですけど、

一応、以下のソースを書いてはみたんですけどね。

 

final_magic/kvs_handle.php at master · kitoku-magic/final_magic · GitHub

 

final_magic/kvs_handle_memcache.php at master · kitoku-magic/final_magic · GitHub

 

final_magic/kvs_handle_redis.php at master · kitoku-magic/final_magic · GitHub

 

ただ、ソース内にも書いている以下のリンクの内容もそうですし、

「ロックを取得した後にトランザクションが失敗したら、ロックは解放するのか」とか、

「複雑な更新処理にしてしまうと、ロールバックが難しくなるので注意」とか、色々と考える必要がある点も別途ある印象でして、

そこまで考える必要あるなら、やっぱりRDBでやった方がという気もしますね。

 

dekokun.github.io

 

元々、「パフォーマンスを良くしたい」って目的からこの話って出てきているんだと思うんですけど、

正直「諸刃の剣(かどうかも怪しい、どれくらい効果があるか未知数ですし)」と思われるこの機能を充実させるよりも、

サーバの増設・増強、言語やフレームワーク自体の性能改善、プログラムのデータ構造やアルゴリズムの工夫、RDBSQLの性能改善などなど、他の比較的リスクの低いチューニングをやった「後に」手を付けた方が良い印象ですね。

でも、上記の1番の言語もそうですけど、

色々見ている限り、そこまではチューニングしていないケースの方が多い印象ですし、そっちが先じゃないかと思いましたね。

あぁ、そういう意味では、先日書いた論理削除の話も同じですね。

というかこっちは、パフォーマンスに好影響ある?って印象なんですけど。

 

ということで、出来れば使いたくない機能ですけど、実装してみたという変な話でした(笑)