奇特なブログ

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

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

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

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

 

まず、情報提供を希望したいんですけど、「国内・国外問わず、性犯罪率を低下させる目的の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番の言語もそうですけど、

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

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

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

 

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

論理削除の考察

えっと、以前に以下に書いたんですけど、
ちょっと今回、この点について真剣に考えてみましょうということで。


kitoku-magic.hatenablog.com


ひとまずは、考えについて整理するということで、
上記記事のリンク先の内容について突っ込んでいってから、
まとめを書きたいと思います。

ただ、「物凄く長い記事」なので、結論だけ知りたい方はこちらを。


http://mike-neck.hatenadiary.com/entry/2015/03/24/231422 から引用。

カーディナリティが云々で検索条件につけても性能上的にもよくない

0と1という二つの値しか取り得ないから、インデックス貼っても大して速くならないといった所でしょうか。
ただ、この記事の最後に書いてある

二つの値でも片方が極端に少ない、片方が極端に多い場合は意味あるらしい

というのもあるみたいですね。


論理削除というのはまだ要件的に未確定な要素が隠されていることを示すフラグ

これ、この後も沢山出てくるんですけど、結構ポイントだと思いますね。


「社員」はマスターと言っていましたが、マスター(僕はリソースと呼んでいる)はシステムの開始から未来永劫追加・変更・削除することができないデータ

ここちょっと興味あったんですけど、「マスター」ってどういうテーブルをイメージします?
個人的には、「商品・社員・アプリ上で表示するメッセージ」といった、
「管理や運営側は変更出来るけど、ユーザーが直接変更出来ないデータ」を「マスター」と呼んでいるんですけどね。
というか、上記の「システムの開始から未来永劫追加・変更・削除することができないデータ」というのがピンとこなかった。
「追加・変更・削除しないデータ」ってあるかなぁと。
まぁ、あんまり本題と関係ないので次へ。


http://blog.kazuhooku.com/2015/03/blog-post_26.html から引用。

「現在の状態を表現するビュー」を実体化したものとして表現されること

あぁ、どうやらココ、「DBA視点」と「アプリ(といってもサーバ側だが)エンジニア視点」で、
「DBに対する考え方が違う」のかなと。
僕は、アプリ(しつこいけどサーバ側)エンジニアなわけですけど、
ビューとかトリガーとかストアドとかファンクションとかって基本否定的でして。
というのも、「ロジックをDB側に書きたくない」というのがあるんですよね。
あと、トリガーに限っていえば、過去に2~3日ハマった事があるというのもあるんですけど(苦笑)
DBは、「データ格納倉庫」として使いたいんですよ。
ただ、後で散々出てくる「制約(ユニーク制約とか)」は使いたいんですけどね。
でも、「手続き型の処理(ストアドやファンクションの事)とか、AをしたらBをする(トリガーの事)」とかは、
プログラム側に一元化したいなぁ。それで「仕事が増えた」としてもね。
・・・ビューは、「ビューのビュー」とか、「複雑化しませんか?」といった懸念や、
以下の記事辺りから、「まぁあんまり」という感じですね。


ビューの功罪


で、多分、「DBの方でやらないでアプリの方でやる」の一番大きな理由としては、「仕様変更に対応しやすくしたいから」だと思いますね。
・・・といってもまぁ、アプリエンジニア間でも、意見が割れそうではありますけどね(苦笑)

なので、上記の話については、特に否定もしないけど肯定もしないといった所ですね。
そもそもの前提が違うので。


http://frsyuki.hatenablog.com/entry/2015/03/26/080627 から引用。

WebサービスとかTreasure Dataのようなサービス事業者だと、テーブルを最初に設計するときにあまり時間をかけられないので、後から見直して最適化していくことが多い

この記事も、基本さっきの話と同じ感じなんですけど、上記については
「だったら、尚更テーブル設計はシンプルにしておきたくないか?」と思うんですよね。
あと、この記事の場合、ポスグレに依存してるのでってのもあるかなと。
いや、MySQLにも対応させたいですからね。


でもPlazmaDBの実装は、ほぼ全部FUNCTIONになっている

これ、リンク先も読んでみたんですけど、「どこにFUNCTIONなんて書いてある?」のか、ちょっと見つけられなかったですね。
単純に、僕が気付かなかった可能性も高そうですけど。


http://blog.webcreativepark.net/2008/05/26-103152.html から引用。

user_mst テーブルに対して、deleted_user_mst テーブルを用意しておいて、ユーザの削除時は、user_mst テーブルから DELETE すると同時に、deleted_user_mst テーブルに INSERT するという方法です

コメントからの引用ですけど、
これ、この後も沢山出てきますね。
というか、僕の知り合いも同じ様な事言ってましたけど。


開発時はこまめにバックアップを取る

開発サーバは何とも言えないですけど、本番でバックアップ取らないってのは全然イメージ無いですね。
正直、「良い度胸してるな」って感じです(苦笑)


テストや検証の工数が取れない場合

この辺が、削除フラグ導入の一因になってる可能性も高そうですね(苦笑)
でもコレ、その時は良くても、後からじわじわと困っていきますしねぇ。


http://qiita.com/Jxck_/items/156d0a231c6968f2a474 から引用。

「最適な設計は DELETE_FLAG ではない」という場合が有って、その場合は、その最適な設計を探すのが正しいだろ

これは、この後も散々出てくるんですけど、「とても大事なポイント」だと思いますね。
「状態」とか、他の意味が隠されているんじゃないの?って。


大抵、色々仕様を見返すと「こういう状態もありますよね?」とこちらが気づくくらいには見落としがあって、
これは放っておいたら、状態が発見されるたびに FLAG 列が追加

で、名前が「~FLAG2」とか、数字の連番になっていくわけですよね(苦笑)


しかし、これはマスタ系のテーブルだと上手く行きません。
例えば社員表から退職者を移すなどと言う場合、その退職者の ID は多くのテーブルから参照されており、
その参照をどうするかが最大の課題となります

あぁ、なるほど。
・・・ゲームの案件(だけ?)で良く見るんですけど、
「マスター系のデータは、DBではなくCSVの中に入れて、使いたい時には、CSVをインポートしてパースする」なんてのがありますね。
で、こっちだと、「社員が退職したらCSVから行を削除」でいけないですかね。
当然、外部キーは貼ってないわけですし。
といっても、結構この辺モヤってますけど。
ただ、こっちの場合、プログラム内で扱うデータの量が増えるので、「メモリに注意」とはなるんですけどね。

・・・あぁ、社員が退職に限っていえば、「退職」って多分ステータスだと思うので(在籍とか出向ってステータスもあるかと)、
単純に、社員テーブルに「在籍状態」ってカラムを用意して、それでさばくとか。
カードゲームのユーザーが所有しているカードのテーブルなら、
「売却(といっても、こっちはマスターじゃないので、削除テーブルに突っ込むで良いのでは?)」とか。

まぁ、上記の方法のいずれでもダメなら、最悪「マスター系だけは削除フラグ使う」となるかもですけど。


パーティションのキーとなる状態があればいい

それこそ、さっきの「在籍状態」とか。
といっても、これはOracleでしか使えない?ので今一つですけど。


問題は、本当にそんな場合があるのか、安易なフラグを付けることによって設計にしわ寄せがいったとしてもフラグを付けるだけの価値があるか、物理設計のツケを論理設計で払うのが本当に良いのか、つける前に検証する価値は有ると思います。推測しないで計測せよという話です

ということで、「計測」してみました。
あと、ここから「物凄く長い」ので注意です。
計測結果による結論だけ知りたいって方は、こちらを。


まず、MySQLのバージョンは「5.5.29」です。
・・・余談ですけど、はてなブログHTML微妙に書きにくい(苦笑)


1.以下のテーブルを用意


// 有効なユーザーのみ格納するテーブル
CREATE TABLE `users_test1` (
`user_id` bigint unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL DEFAULT '',
PRIMARY KEY (`user_id`)
) engine = InnoDB default charset = utf8;

// 無効(削除とか)なユーザーを格納するテーブル
CREATE TABLE `delete_users` (
`delete_id` bigint unsigned NOT NULL AUTO_INCREMENT,
`user_id` bigint unsigned NOT NULL,
`name` varchar(50) NOT NULL DEFAULT '',
`delete_time` datetime NOT NULL,
PRIMARY KEY (`delete_id`),
KEY (`user_id`)
) engine = InnoDB default charset = utf8;


// delete_flag有りのユーザーのテーブル
CREATE TABLE `users_test2` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT,
`user_id` bigint unsigned NOT NULL,
`name` varchar(50) NOT NULL DEFAULT '',
`delete_flag` tinyint NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
KEY (`user_id`, `delete_flag`)
) engine = InnoDB default charset = utf8;

// ユーザーIDの現在値(色々あって、こうせざるを得なかったんですよね)
CREATE TABLE `user_id_seq` (
`current_user_id` bigint unsigned NOT NULL DEFAULT 0,
PRIMARY KEY (`current_user_id`)
) engine = InnoDB default charset = utf8;

INSERT INTO user_id_seq VALUES (0);

まぁ、テーブルをどうやって切るかも色々ありそうですけど、
ひとまず、こんな形に。


2.テーブルにデータ突っ込むPHP


// data_insert_users_test1.php
// users_test1テーブルに百万件のレコードを作成する
<?php

try
{
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8', 'ユーザー名', 'パスワード', array(PDO::ATTR_EMULATE_PREPARES => false));
}
catch (PDOException $e)
{
exit('データベース接続失敗:' . $e->getMessage());
}

$pdo->beginTransaction();

for ($i = 1; $i <= 1000000; $i++)
{
if ($i >= 10000 && $i % 10000 === 1)
{
$pdo->beginTransaction();
}
$stmt = $pdo->prepare("INSERT INTO users_test1 (name) VALUES (:name)");
$stmt->bindValue(':name', uniqid('', true), PDO::PARAM_STR);

$ret = $stmt->execute();
if ($ret)
{
if ($i >= 10000 && $i % 10000 === 0)
{
$pdo->commit();
}
}
else
{
echo "データ追加失敗\n";
$pdo->rollback();
exit;
}
}


// data_insert_delete_users.php
// delete_usersテーブルに二百万件のレコードを作成する
// 1ユーザーあたり、2件の削除レコードが存在する
<?php

try
{
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8', 'ユーザー名', 'パスワード', array(PDO::ATTR_EMULATE_PREPARES => false));
}
catch (PDOException $e)
{
exit('データベース接続失敗:' . $e->getMessage());
}

$stmt = $pdo->prepare("SELECT * FROM users_test1 ORDER BY user_id");
$ret = $stmt->execute();

if ($ret)
{
$pdo->beginTransaction();
while ($result = $stmt->fetch(PDO::FETCH_ASSOC))
{
if ($result['user_id'] >= 10000 && $result['user_id'] % 10000 === 1)
{
$pdo->beginTransaction();
}
$stmt1 = $pdo->prepare("INSERT INTO delete_users (user_id, name, delete_time) VALUES (:user_id, :name, :delete_time)");
$stmt1->bindValue(':user_id', $result['user_id'], PDO::PARAM_INT);
$stmt1->bindValue(':name', $result['name'], PDO::PARAM_STR);
$stmt1->bindValue(':delete_time', date('Y/m/d H:i:s'), PDO::PARAM_STR);

$ret = $stmt1->execute();
if ($ret)
{
$stmt2 = $pdo->prepare("INSERT INTO delete_users (user_id, name, delete_time) VALUES (:user_id, :name, :delete_time)");
$stmt2->bindValue(':user_id', $result['user_id'], PDO::PARAM_INT);
$stmt2->bindValue(':name', $result['name'], PDO::PARAM_STR);
$stmt2->bindValue(':delete_time', date('Y/m/d H:i:s', strtotime('+1 day')), PDO::PARAM_STR);

$ret = $stmt2->execute();
if ($ret)
{
if ($result['user_id'] >= 10000 && $result['user_id'] % 10000 === 0)
{
$pdo->commit();
}
}
else
{
echo "データ追加失敗\n";
$pdo->rollback();
exit;
}
}
else
{
echo "データ追加失敗\n";
$pdo->rollback();
exit;
}
}
}
else
{
echo "SELECT失敗\n";
exit;
}


// data_insert_users_test2.php
// users_test2テーブルに三百万件のレコードを作成する
// 百万件はdelete_flagが0で、残りはdelete_flagが1
<?php

try
{
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8', 'ユーザー名', 'パスワード', array(PDO::ATTR_EMULATE_PREPARES => false));
}
catch (PDOException $e)
{
exit('データベース接続失敗:' . $e->getMessage());
}

$pdo->beginTransaction();

for ($i = 1; $i <= 1000000; $i++)
{
if ($i >= 10000 && $i % 10000 === 1)
{
$pdo->beginTransaction();
}
$name = uniqid('', true);
$stmt = $pdo->prepare("INSERT INTO users_test2 (user_id, name, delete_flag) VALUES (:user_id, :name, :delete_flag)");
$stmt->bindValue(':user_id', $i, PDO::PARAM_INT);
$stmt->bindValue(':name', $name, PDO::PARAM_STR);
$stmt->bindValue(':delete_flag', 0, PDO::PARAM_INT);

$ret = $stmt->execute();
if ($ret)
{
$stmt1 = $pdo->prepare("INSERT INTO users_test2 (user_id, name, delete_flag) VALUES (:user_id, :name, :delete_flag)");
$stmt1->bindValue(':user_id', $i, PDO::PARAM_INT);
$stmt1->bindValue(':name', $name, PDO::PARAM_STR);
$stmt1->bindValue(':delete_flag', 1, PDO::PARAM_INT);

$ret = $stmt1->execute();
if ($ret)
{
$stmt2 = $pdo->prepare("INSERT INTO users_test2 (user_id, name, delete_flag) VALUES (:user_id, :name, :delete_flag)");
$stmt2->bindValue(':user_id', $i, PDO::PARAM_INT);
$stmt2->bindValue(':name', $name, PDO::PARAM_STR);
$stmt2->bindValue(':delete_flag', 1, PDO::PARAM_INT);

$ret = $stmt2->execute();
if ($ret)
{
if ($i >= 10000 && $i % 10000 === 0)
{
$pdo->commit();
}
}
else
{
echo "データ追加失敗\n";
$pdo->rollback();
exit;
}
}
else
{
echo "データ追加失敗\n";
$pdo->rollback();
exit;
}
}
else
{
echo "データ追加失敗\n";
$pdo->rollback();
exit;
}
}

$pdo->beginTransaction();

$stmt = $pdo->prepare("UPDATE user_id_seq SET current_user_id = 1000000");

$ret = $stmt->execute();

if ($ret)
{
$pdo->commit();
}
else
{
echo "データ追加失敗\n";
$pdo->rollback();
}


ちなみに、今更気付いたんですけど、
削除テーブルに同じユーザーが二人って変だから、
ユーザーじゃない(履歴的なテーブルであれば良いわけですし)方が良かったですね(苦笑)
まぁ、今回の本筋とは関係ないと思うので、今回はこのままいきます。


3.SELECT文を投げて速度計測


// 有効なユーザーデータのみ取得
select user_id, name from users_test1 where user_id = 492650;

select user_id, name from users_test2 where user_id = 492650 and delete_flag = 0;


// 無効なユーザーデータも含めて取得
select user_id, name from users_test1 where user_id = 492650
UNION ALL
select user_id, name from delete_users where user_id = 492650;

select user_id, name from users_test2 where user_id = 492650;


mysql> set profiling = 1;
Query OK, 0 rows affected (0.00 sec)

mysql> select user_id, name from users_test1 where user_id = 492650;

user_id name
492650 5600e36c5e6b81.87318120

1 row in set (0.00 sec)

mysql>
mysql> select user_id, name from users_test2 where user_id = 492650 and delete_flag = 0;

user_id name
492650 5600f48c5dade8.64925888

1 row in set (0.00 sec)

mysql> select user_id, name from users_test1 where user_id = 492650
-> UNION ALL
-> select user_id, name from delete_users where user_id = 492650;

user_id name
492650 5600e36c5e6b81.87318120
492650 5600e36c5e6b81.87318120
492650 5600e36c5e6b81.87318120

3 rows in set (0.00 sec)

mysql>
mysql> select user_id, name from users_test2 where user_id = 492650;

user_id name
492650 5600f48c5dade8.64925888
492650 5600f48c5dade8.64925888
492650 5600f48c5dade8.64925888

3 rows in set (0.00 sec)

mysql> select user_id, name from users_test1 where user_id = 492650;

user_id name
492650 5600e36c5e6b81.87318120

1 row in set (0.00 sec)

mysql>
mysql> select user_id, name from users_test2 where user_id = 492650 and delete_flag = 0;

user_id name
492650 5600f48c5dade8.64925888

1 row in set (0.00 sec)

mysql> select user_id, name from users_test1 where user_id = 492650
-> UNION ALL
-> select user_id, name from delete_users where user_id = 492650;

user_id name
492650 5600e36c5e6b81.87318120
492650 5600e36c5e6b81.87318120
492650 5600e36c5e6b81.87318120

3 rows in set (0.00 sec)

mysql>
mysql> select user_id, name from users_test2 where user_id = 492650;

user_id name
492650 5600f48c5dade8.64925888
492650 5600f48c5dade8.64925888
492650 5600f48c5dade8.64925888

3 rows in set (0.00 sec)

mysql> show profiles;

Query_ID Duration Query
1 0.00042075 select user_id, name from users_test1 where user_id = 492650
2 0.00025525 select user_id, name from users_test2 where user_id = 492650 and delete_flag = 0
3 0.00049375 select user_id, name from users_test1 where user_id = 492650

UNION ALL
select user_id, name from delete_users where user_id = 492650 |

4 0.00021150 select user_id, name from users_test2 where user_id = 492650
5 0.00029775 select user_id, name from users_test1 where user_id = 492650
6 0.00022225 select user_id, name from users_test2 where user_id = 492650 and delete_flag = 0
7 0.00048450 select user_id, name from users_test1 where user_id = 492650

UNION ALL
select user_id, name from delete_users where user_id = 492650 |

8 0.00020925 select user_id, name from users_test2 where user_id = 492650

8 rows in set (0.00 sec)

mysql>


UNION ALLが若干遅い(といっても、ミリ秒レベルの話ですけど)けど、
そんなに変わらんって所でしょうか。
ちなみに、同じSQL二回投げたのは、キャッシュを利かせて同じ条件にする為です。
キャッシュ利いていない同じ条件の場合は・・・また今度にしましょう。


3.ユーザーの削除処理を実行し速度計測


// data_delete_users_test1.php
// users_test1テーブルのレコードを削除し、delete_usersに追加する
<?php

// コマンドライン引数からユーザーIDを渡す前提
$user_id = $argv[1];
$time_start = 0;
$time_end = 0;

try
{
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8', 'ユーザー名', 'パスワード', array(PDO::ATTR_EMULATE_PREPARES => false));
}
catch (PDOException $e)
{
exit('データベース接続失敗:' . $e->getMessage());
}

$time_start = microtime(true);

$stmt = $pdo->prepare("SELECT * FROM users_test1 where user_id = :user_id");
$stmt->bindValue(':user_id', $user_id, PDO::PARAM_INT);
$ret = $stmt->execute();

if ($ret)
{
$pdo->beginTransaction();
while ($result = $stmt->fetch(PDO::FETCH_ASSOC))
{
$stmt1 = $pdo->prepare("DELETE FROM users_test1 where user_id = :user_id");
$stmt1->bindValue(':user_id', $result['user_id'], PDO::PARAM_INT);

$ret = $stmt1->execute();

if ($ret)
{
$stmt1 = $pdo->prepare("INSERT INTO delete_users (user_id, name, delete_time) VALUES (:user_id, :name, :delete_time)");
$stmt1->bindValue(':user_id', $result['user_id'], PDO::PARAM_INT);
$stmt1->bindValue(':name', $result['name'], PDO::PARAM_STR);
$stmt1->bindValue(':delete_time', date('Y/m/d H:i:s'), PDO::PARAM_STR);

$ret = $stmt1->execute();
if ($ret)
{
$pdo->commit();
}
else
{
echo "データ追加失敗\n";
$pdo->rollback();
exit;
}
}
else
{
echo "データ削除失敗\n";
$pdo->rollback();
exit;
}
}
$time_end = microtime(true);
}

echo $time_end - $time_start . "\n";


// data_delete_users_test2.php
// users_test2テーブルdelete_flagが0の行を1に更新する
<?php

// コマンドライン引数からユーザーIDを渡す前提
$user_id = $argv[1];
$time_start = 0;
$time_end = 0;

try
{
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8', 'ユーザー名', 'パスワード', array(PDO::ATTR_EMULATE_PREPARES => false));
}
catch (PDOException $e)
{
exit('データベース接続失敗:' . $e->getMessage());
}

$time_start = microtime(true);
$pdo->beginTransaction();
$stmt = $pdo->prepare("UPDATE users_test2 SET delete_flag = 1 where user_id = :user_id and delete_flag = 0");
$stmt->bindValue(':user_id', $user_id, PDO::PARAM_INT);

$ret = $stmt->execute();

if ($ret)
{
$pdo->commit();
}
else
{
echo "データ更新失敗\n";
$pdo->rollback();
exit;
}
$time_end = microtime(true);

echo $time_end - $time_start . "\n";


で、上記PHPを、以下のコマンドで実行しました。


for i in `seq 1 1 1000`; do php data_delete_users_test1.php $i >> result_data_delete_users_test1.xls; done


for i in `seq 1 1 1000`; do php data_delete_users_test2.php $i >> result_data_delete_users_test2.xls; done


で、エクセルファイルに書き込まれた実行時間の平均を取った結果、
users_test1が「0.1151350505秒」で、
users_test2が「0.1165583317秒」となりましたって、
削除フラグ無いusers_test1の方がむしろ速いんですけど。


とりあえず、計測の結論としては、
「ほとんど変わらん」のではないかと。
勿論、前提変われば結果も変わるとは思うので、
テーブル設計やプログラムが変って所があれば、ご指摘頂きたい所ではありますけど。

では、話を戻して続きを。


http://qiita.com/Jxck_/items/156d0a231c6968f2a474 から引用。

「論理削除した行が復活する事」は、オペレーションミスの訂正時にもありますね。
オペレーションミスの訂正は画面を閉じた後でも発生するので、アンドゥ機能では対応できません。

ここからは、コメントからの引用ですけど、
オペミスがあるから、delete_flagを付けると?
「管理画面で確認ダイアログ出す」とか、
「万が一オペミスした場合のレコード復旧機能を、別途作る」とか、
色々工夫は出来ると思うんですけどね。
ちなみに、どうやってレコードを復旧させるかについては、
「削除テーブルに入れてしまったレコードを、有効テーブルに戻す」プログラムを書けば良いと思います。
まぁ、削除テーブルのdelete_idが歯抜けにはなっちゃいますけど、
このID自体、特に業務用のIDでも無い(サロゲートキー)ですし、仕方ないかと。


ちなみに、私は、作成日・更新日も何も考えずに項目に入っているのも嫌です。
JSON形式として更新前イメージをすべてログを残しておくようにしています

この作成日・更新日も多いですね。
まぁ、JSON形式かどうかはともかく、確かにログに残す方が良いと思いますね。


しかし、実際は要件定義には手をつけられないのもよくあること。私はその場合、特段問題が無い限り削除フラグやバックアップテーブルなど「意図しない不要データ」を許容してしまいます。思考停止というより(開発では)QCDに見合わないですからね。運用段階で、運用改善、パフォーマンス改善として予算取りするという政治的解決が待っていますorz

まぁ、ぶっちゃけこういった「時間が無いから」ってケースも多そうですね(苦笑)
でも、後で面倒になりますから、やっぱり時間は割くべきかと。
「自分で自分の首を絞める形になる」前に。


昔アプリ不具合でselect文のwhere句部分が無くなる

これ、SQLインジェクションじゃないですかね。
まぁ、本題と全然関係ないですけど。


http://qiita.com/yuba/items/70165875cfe02b03513d から引用。

アドレスとstatusの組をキーに一意性制約をかけます。削除済みユーザはNULLがキーに含まれるので一意性の判定対象にならないという次第。表技感あふれてますね

そうそう、さっき上記のプログラム書いてた時に、ユニークに出来ないんだがと思っていたんですけど、
で、こういう方法があるよと。
といっても、NULLは「3値論理」がねぇ。
以下の通り、結構ややこしいですし、正直覚えてられん。


codezine.jp


http://dekasasaki.tumblr.com/post/69487259373/%E8%AB%96%E7%90%86%E5%89%8A%E9%99%A4%E3%81%8C%E5%A5%AA%E3%81%86%E3%82%82%E3%81%AE から引用。

「あるエンティティ定義に、論理削除有無を設定する属性が定義されている時点で、開発者は『ああ、この表のデータって削除していいんだ』という暗黙の了解に思考を縛られる」

なるほど、こういった心理的副作用は怖いですね。


http://www.infoq.com/jp/news/2009/09/Do-Not-Delete-Data から引用。

注文は削除されません。– キャンセルされるのです。キャンセルが遅かったら、料金が発生するでしょう。
従業員は削除されません。– 解雇されるのです(あるいは退職かもしれません)。 給与体系は頻繁に手を入れなければなりません 。
仕事も削除されません。– 完了されるのです(または、取り消されるかもしれません)。
どんな場合でも、着目すべきはユーザが行いたい作業であり、エンティティその他に対する技術的な処理ではありません。ユーザの作業に着目すれば、ほとんどすべての場合、1つ以上のエンティティを考慮しなければならないはずです。

どう見ても削除じゃないですね、コレ。
だから、「状態があるものを、削除フラグで扱うな」となる。


http://d.hatena.ne.jp/jflute/20121116/1353001525 から引用。

ユニーク制約がないと何が困るかって、
一言でずばり「なんでも入っちゃう」ってところ。
要は「FOO=A, BAR=B, DEL_FLG=false」も、
複数入ってしまう可能性があるってこと

ですねぇ、制約で防げる所は防ぎたいです。


ふとしたときに重複データが入ってしまって、
「一件検索が二件になってエラーになっちゃった」とか

はいはい(苦笑)


削除フラグだけじゃなく、削除日時みたいなカラムを用意して、
有効なデータには固定の "9999/12/31" とか入れて、
削除されたデータには削除した日時をそのまんま入れる。
「FOOとBARと削除日時」でユニーク制約

でも、これ「同じ日(あるいは、同じ時間)」だったらアウトになりますよね。
まぁ、同じ時間(秒まで同じ)はそうそうないのは確かですけど。


削除フラグにはDBコメントが絶対に必須

もし入れるなら、確かに必須レベルかと。


そもそも有効Table作っときゃいいだけなんじゃないですかね?

こんなTableが有ったとして
create table Master
(
id serial primary key,
column1 text,
column2 text,
column3 text
);

こんな感じで生存しているRecordのIDだけを保持する有効Tableを用意します。
create table ActiveMaster
(
  id integer references Master( id ) on delete cascade
);
Masterの検索削除を行う際は、この有効Table使って操作します。例えば削除する場合は、ActiveMasterのRecordだけをdeleteします。


ぱっと見、削除Flagと大差ありませんが、ActiveMasterに対しinsertとdeleteを行うことで追加削除ができ、やや直感的になります。また、検索時に分散Indexなんかを使わなくとも削除した項目を検索対象にしないので高速です。参照制約も活用しやすくなりますよ

これはコメントからですけど、ほほう、またさっきの僕のとは違うアプローチですね。
ただコレ、使い方がちょっと分かりにくい・・・

Masterテーブルには「削除されたレコードも含めた全件」が入っていて、
そのうち、有効なレコード「だけ」が、ActiveMasterに入ってるって事かと思うんですけど。
ちょっと、上記の僕のusersテーブルに合わせると、以下の様になりますかね。


CREATE TABLE `users_test3` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT,
`user_id` bigint unsigned NOT NULL,
`name` varchar(50) NOT NULL DEFAULT '',
PRIMARY KEY (`id`),
KEY (`user_id`)
) engine = InnoDB default charset = utf8;

CREATE TABLE `active_users_test3`
(
`id` bigint unsigned NOT NULL,
`user_id` bigint unsigned NOT NULL,
PRIMARY KEY (id),
UNIQUE KEY (user_id),
foreign key(id) references users_test3(id) on delete cascade,
foreign key(user_id) references users_test3(user_id) on delete cascade
) engine = InnoDB default charset = utf8;

CREATE TABLE `user_id_seq` (
`current_user_id` bigint unsigned NOT NULL DEFAULT 0,
PRIMARY KEY (`current_user_id`)
) engine = InnoDB default charset = utf8;

INSERT INTO user_id_seq VALUES (0);

う~ん、user_id_seqが余分ですねぇ。
あと、出来るだけサロゲートキーも使いたくないしねぇ。
で、SELECTは、


select * from users_test3 ut where ut.user_id = (select aut.user_id from active_users_test3 aut where aut.user_id = ?);


という感じ(あくまで一例だが)でしょうか。
あと、INSERTは、「両方のテーブルに追加」が必要で、
UPDATEは、「users_test3の方だけ」で、
DELETEは、「active_users_test3の方だけ」でという感じでしょうか。
まぁ、悪くはないですけど、やはり前述のテーブルの方が良い様に思えますね。
いや、もしかしたら、使い方が間違っているのかもしれないですけど。

話を戻して次。


http://d.hatena.ne.jp/ryousanngata/20150329/1427647377 から引用。

1.名前から目的が明確にならない
2.バグの要因の一つ (認識の祖語を生みやすいし、SQLを注意して書かないと実装バグを起こしやすい。)
3.テストするにも論理削除状態のデータを1個置いてテストするようなことをしないといけない

1番目は、だからコメントをって話だと思いますし、
3番目は、なるほどこういう手間も確かにありますね。


ただし論理削除に慣れてきてしまうと、本当に削除していいのか判断ができなくなり、とりあえず論理削除を設計に盛り込むようになる。
他のシステムもやってるしーみたいなノリで入れ始める

確かに、こういったケースで導入してる場合もありそう(苦笑)


SELECT文の条件で意識しないといけない(この操作のときはチェックすべきなのか否か)

あぁ、そうそう、これ以前の仕事中にありましたね。
で、こういう時にメンドイ(というか迷う)と。


ものぐさには2つのテーブルを行ったり来たりする気力はないかもしれない。(自分はそう思います)

う~む、そうなのか?
いや、そこまで面倒じゃないと思うんですけどね・・・


この発想に至るのは「ログは1か所で管理しろ」という点に尽きる。つまり、DBはログを管理する場所ではない。

テキストベースのログとDBの論理削除されたレコードのタイムスタンプ比較して多分このレコードはここの操作にあたるな?とアタリをつけて調べるのは辛い。

ログは大量に出るので時系列で追おうとすると、途端に辛くなりますが、ユーザの識別子(ID)とかをログに出すようにすればgrepすればある程度は追いやすくなるし、最近はJSONにしてDBにぶっこんで調べるというのも実用レベルで聞くし、ログはログでまとめたほうが良いのではと思ってる

あぁ、確かにログは1か所の方が良いと思いますね。
で、ユーザの識別子をログに出してってのは、やってる現場ありましたね。
で、確かに調べやすかった。


http://blog.crossidea.co.jp/2013/501/ から引用。

間違えて登録したデータを完全に削除できないのは困る。
あるデータに関しては通常の運用で完全に削除したい。

あぁ、でもコレは論理削除使ってても、定期的にバッチ回して消すとかで対応可能ですけどね。
ただ、特定のデータだと、絞り込めないですね(delete_timeなら絞り込めるけど)。


情報資産というのはデータの所有者が、それを保有することに価値を見出している情報という意味です。一定の役目を終えたからと言って完全に削除してしまうと、新たなデータの参考にすることすらできなくなります。その場合は論理削除が良いのではないかと思っています

いや、それこそ履歴(削除テーブルの事)に持たせれば良いじゃないですか。


http://makopi23.blog.fc2.com/blog-entry-176.html から引用。

Webアプリとかでは、パフォーマンスの問題を考慮して物理削除を行わない場合がある。
秒間1億のトランザクションを捌くのに、物理削除は難しい。

これ、よく聞く論調の話ではあるんですけど、
上記の計測結果を見るとなぁって感じでもあるんですよね。
いや、勿論条件が全然違うのは分かりますけど、これは誰が言い始めたのかが気にならないでもないですね。


「製品名」が変更になった場合、そのレコードを新規追加し、更新次数を0とする。他のレコードは更新次数をすべて +1 してズラす

う~ん、話としては分かりますけど、ちょっと面倒じゃないですかねコレ。


レコードには「開始日付」と「終了日付」を持たせる。
あるレコードの「終了日付」と、次に新しいレコードの「開始日付」は、一致させること。
日付に連続性を持たせ、Select文のWhere句で "where 開始日付 <= Target and Target < 終了日付"のように指定する。
下限を ≦ にして上限を < にする点がポイント。これによりレコードの連続性を保つ。betweenは使えない。
あるレコードの開始日付と終了日付を同じ値にすることで、そのレコードを論理削除したことと同一になる。

要するに、履歴を管理したいって事だと思いますけど、
それは、削除テーブルのdelete_timeで出来ると思うんですけどね。


http://blogs.wankuma.com/kacchan6/archive/2007/08/21/91190.aspx から引用。

現在の業務アプリはJSOXの絡みもあってDELETEは一切ご法度。
UPDATEもすべてトリガでログするかなどの消える処理はご法度です

JSOX、ほほうまた新たな観点が。
といっても、それも削除テーブルを見れば良いんじゃないかと。


もう使わないマスタデータだけれども過去のデータでマスタ参照しているものもあるので、そういったものは論理削除(削除フラグ=On)

これがちょっとな・・・まだモヤってますね。


http://blog.mogmet.com/ronsakucasual-1/ から引用。

やってみると結構難しい
1個のテーブルだけではなく、お互いのテーブルの関係などを考えると結構大変

履歴テーブルで管理するのが難しいって事ですけど、
確かに最初は、論理削除と比べて手間がかかるとは思いますね。
なので、あまりにも時間がない時(それはそれで、別の問題がある様にも思うので、そっちの改善をした方が良いですが、それでもダメなら)には、
論理削除の方が良いとは思いますね。


絶版商品に削除フラグを付けて、一覧や検索で表示されないようにしたい

ほんとうに欲しかったのもはstatus = :絶版

またしても、フラグでは無かったパターンですね。


退会した会員はログイン出来ないように論理削除したい

そのまま残してstatus = :ログイン不可にする

これも同じですね。
で、どういうマスターかにもよりますけど、マスターもこれで良いのでは。


保管期間の過ぎたデータに削除フラグをたてたい

古いやつを消したいというニーズは新しいものを表示したいというニーズではないのか

これは、以前にポイントの履歴を格納するテーブルがありまして、
「ポイントは半年間のみ有効だが、それ以前は無効になる」なんて時に、
「無効になったポイントは、別のテーブルに移す」なんてのが有効じゃないかというのがありましたね。
勿論、SQLで期間指定する方法もあるけど、
定期的にバッチを実行して、移した方が良いんじゃないかと。


http://ledsun.hatenablog.com/entry/2015/03/27/015203/ から引用。

アプリケーションの作成工数や運用工数が、データ設計工数より低い

これは、「データ設計工数がたっぷり取られていて、散々検討した結果、不要な削除フラグは排除されているので、
そういった中で導入した削除フラグについては仕方ない」のでOKって事ですかねぇ。
まぁでも確かに、要件として含まれていた場合にはとかも考えると、これは良いのではないかと。
ただ、個人的経験ですと、
「むしろ、アプリの作成工数や運用工数の方が、データ設計工数より"圧倒的に"多いよ」って印象で、
でも、そんな現場で削除フラグで導入されていて、これまでに色々書かれていた問題が発生したりしているので、
上記の意見は満更でもないですね。

結論


長々と書いてきましたが、以下の点がポイントなんじゃないかと。


1.要件を整理すること。それは本当に「削除」なのか、「状態」ではないのかとか。


これまで散々書かれていた事で、これがやっぱり一番重要だと思いますね。
で、その上で削除フラグ(フラグじゃなくて時間かもしれないが)導入はアリかと。
あと、ココは工数が足りなくて~もあるかと思うので、
エンジニア以外のメンバーの協力も必要かと。


2.パフォーマンスについては「計測」すべし。


上記の計測の通りですね。
あと、パフォーマンスって別にDB(というかSQL)だけじゃなくて、
Webサーバ・プログラム(FWやORマッパーも含む)・クライアント側のプログラム・スケールアウト・スケールアップ・DBのパラメータチューニングとか、
他にも色々あると思うので、「全体」として見てみたい所ではありますね。


3.オペミスなどからの「データ復旧」は、オペミス発生しづらい仕組み(ダイアログ出すとか)作るなり、復旧機能を作るなり、バックアップから戻せ


手作業はやっぱり大変だと思うので。
バックアップは最終手段にしたいですけどね。


「マスターの一部と大規模Webサービスは削除フラグ導入せざるを得ない?」って所が特にモヤってますけど、
ひとまず、こんな所でしょうか。
個人的には、削除テーブル案をもう少し検証してみたいですけどね。


ご意見・ご感想などありましたら、コメント等でいただければと思います。

追記

記事の途中の速度計測をしている箇所について、
users_test1テーブルを一億件、
delete_usersテーブルを二億件、
users_test2テーブルを三億件にして再計測してみたんですけど、
users_test1が「0.1128752351秒」で、
users_test2が「0.1137793614秒」ということで、
計測前と殆ど変わらなかったという(苦笑)
だから、これはもう速度が遅いという理由で、
論理削除を使う理由はちっとも無い様に思いますね。

Linuxで色々な環境を構築する手順書を書いた件

かなり長くなってしまいましたけど(2600行以上)、

以下に書きました。

 

Linux環境構築手順

 

一番の注目点だと、「本番に上げる設定」ですかね。

皆さん、どうしてるんだろうなぁと。

いや、色々な現場で色々なやり方見てますけどね。

 

といってもコレ、「複数サーバーに対応した設定」とか、

モノによっては「本番サーバーに対応した設定」もありますし、

あと、もう少しコメントを追加したい所もありますね。

まぁ、ゆるゆるとやっていきたいと思います。

 

例によって、何か気になる点ありましたら、ツッコミいただければと思います。

薄利多売だとスピード重視にならざるを得ないんじゃないの?

結論だけ先に。

1.差別化は、薄利多売でも高単価でも大事(競合をよく調べるべし)

2.薄利多売だと、ブラックになりやすく、また多角化しないと中長期的には厳しい

3.サービスに愛着があると、客観的なジャッジが難しくなり、損切りしにくくなるので注意

4.広告・レコメンド系は、もう少し細かくオプトインの条件を設計すれば良いのでは?

5.倫理観を捨てないと稼げない場合は、モデルがそもそも優秀ではないと思われるので、早目に次のモデルを考えるか、倫理観を捨てても稼げる様に改良していかないと、特に風評被害に注意。

6.倫理観捨てないと稼げないケースの時、逆に消費者にバレると都合が悪いので、教育しない方が都合が良いので注意

 

で、タイトルの続きですけど、なので、まず「ビジネスモデルが薄利多売型なのか、客単価が高い(これをなんと言うのか知らんが、高付加価値ビジネス?)モデルなのかを判断する」が一点目。

判断する為の計算式とかあると良いんですけどね。「すぐ離れやすい・Twitterや2ちゃんで不満が多数(○○はクソとか理由が書かれているかどうかも判断基準)出ている」だと、薄利多売系かなぁとかはボンヤリ。

 

閑話休題

 

二点目。薄利多売型なら多くの事業に小さく手を出していかないと、多くの利益が確保出来なくなり(一つの事業での利益が少ないから)。

 

三点目。多くの利益が確保出来ないから、従業員の給料や余暇に回せず(少ない高スキルの人数で回しているならいけると思うが)、結果ブラック企業っぽくなり、風評被害で印象が悪く(最近だとマクドナルドかな)なったり、過労した従業員が辞めたり(特に、その人に依存している場合は代替コストが凄く高い)、引継ぎコスト(簡単なマニュアルで出来る仕事なら大きな問題にはならないと思うが)が嵩んだりするので中長期的には危ない」って所でしょうかね。

 

だから、以下のGE(100年以上の歴史って頭おかしいですね)みたく、リスクヘッジも考慮して、多角的にやれば良いのにっていう。そうすると、嫌でもサーフィン必須になりますけどね。ただ、サーフィンやったら、間違いなく中途半端になるので、その事業ではあまり稼げないでしょうけど、時流の変化には強いでしょうね。むしろ、その中で、「どれが薄利多売路線から抜け出せそうな事業か」を、見極めるのが重要でしょうと。

 

ゼネラル・エレクトリック - Wikipedia

 

あと、特にBtoCに顕著だと思いますけど、最近の消費者は流行り廃りとか多様性とか、一言で言うと「移り変わりが激しい」ので、むしろ高単価ビジネス(お金が無い人も多いでしょうし)は難しいでしょうねって所が、エンジニア(どう見ても、他の職種に比べたら高単価かと)には不利でしょうね。

 

次に、スピード重視になってしまう理由について。

差別化をしていない場合、値段を安くしたり競合他社に合わせて新機能とかをリリースしていかないと"あっちには有るけど、こっちには無いし、似ていてそんなに魅力も感じないから止めた"となり、利益が減少してしまうので、スピード感を持って事業を進めていくしかない。

 

・・・これ、限りなく「必然」に近い気も。

ココに限らないですけど、特にツッコミ希望はココですね。

ということで、薄利多売だけでいきたい場合は「多角的に事業を行う」。

あと、「多売」なので、当然ユーザー数も増やさないとダメですね。

昨今の、「スピード重視で速くユーザー数を増やして!」がよく分かる話じゃないかと。

逆に、高単価を狙いたい場合は「差別化」じゃあないかと。

あ、でも「市場規模」が小さいので、「低単価だけど差別化(これがまた、鋭すぎましてね)して且つ、他の事業(こっちも鋭かったわ)もやって稼いでいる」会社も最近あったので、あんまり関係ないか。コミュニケーション部分「だけ」引っ掛かりましたけど、この辺の詳細は不明。

・・・「市場規模が大きい場合は、あまり差別化を考えなくても、客が来るから大丈夫」って所でしょうか。まさに今のソシャゲがそうですし。

一応、差別化って話だと、以下の永井孝尚さんの本が良いと思いますね。

 

Amazon.co.jp: 永井 孝尚:作品一覧、著者略歴

 

あと、これは翻訳だけど、個人的には次は以下を読みたいかなと。

 

www.amazon.co.jp

 

あと、別の観点で未来予測(つまり、薄利多売が今後高単価系になっていくとか)もありますね。

・・・ただ未来予測は、以下の本にも少し書いてますけど、基本的には「出来ない(失敗についての予測の方が、出来ているケース多い様に思いますね。某図書館とか。)」様に思いますしね。だって、確か「ざっくり」って書いてましたし。

 

www.amazon.co.jp

 

ここまでで「薄利多売ダメって事?」って思った人、ちょっと待て。

というか、興味があったからクリックしたんでしょうし、「サービスに愛着があると損切り出来なく、結構失敗率も高い」を後で書くので。

 

逆に、高単価(最近は難しいかもしれないが)の場合。

一点目。質について満足した場合(なんだこの店?有り得ないぐらい味が良いし、アンケートで気に入らなかった点を堂々と書いてくださいとか、しつこいぐらいに言ってくるし)、"リピーターになりやすい"(もう、他の店行く気しねえや。病みつきになったので)。

ただ、ここで問題なのが、「質について認識出来るのか?」という部分。

以下の店とか、いきなり食べて分かるのかなぁと。

 

渋谷店の特徴|とんかつと旬のお料理 かつ吉 渋谷店|店舗紹介|かつ吉 菩提樹

 

とんかつは・・・多分20~30店舗ぐらい行ってるのかな。ココがダントツでしたね。ただ、「食べ比べない」と、多分わからないんですよね。そういう意味で、高いので上司が奢る(最近は、すっかり無くなったでしょうね)はアリかと。

という意味で、以下の様な事が広まってほしいなと。

 

kitoku-magic.hatenablog.com

 

ただ、上記って、以下とも根っ子は似てる気もしますね。

といっても、以下の場合、上記と違って「どのくらい教えられるのか」ってのも、あると思いますけどね。その点、上記は簡単ですね(笑)

 

 

ただ、上記の「アンケートで気に入らなかった点を堂々と書いてくださいとか、しつこいぐらいに言ってくるし」っていうのは、基本的には良い姿勢だと思いますけど、日本人は以下の通り「妖精なのでやらない」ので。

 

日本人 - chakuwiki

 

じゃあ、やる人は「大体(全員じゃないのでそこは注意)」は「クレーマー」ですね。

で、やらなかった人は、「居酒屋」とか「Twitter」とか「2ちゃんねる」とか「食べログ(これは適当だが)」とかで愚痴ってますと。

そういう意味で、何とも「商売のしづらい人種」ですね。

・・・妥当なツッコミだったら、飯などを奢るとか、「インセンティブ」を与えれば良いのでは。素晴らしい(笑)あ、勿論この記事も対象で(笑)

そういう意味で、この一つ前のエントリーのコメントは、「合格(上記のとんかつとかぐらいならOK)」ですね。

この辺は、以下の記事の後半を少し応用してみました。

 

モラルある行動は教育で生まれるのではなくシステムで作るもの - ベンチャー役員三界に家なし

 

ただ、「なんで、このツッコミが妥当じゃねえんだよ!」ってのもありそうですし、「なんだ、たったこれだけのサービスかよ!(って、やってもらう方が言うなって話ですけど)」ってのは「道徳」的な話でしょうけど。

 

閑話休題

 

二点目。「質が認識出来た場合」が前提ですけど。

すぐには客はいなくならず(といっても、ずっと何もしなければ、流石にいなくなると思うので、スピード感が無さすぎるのも、また問題)、当面の利益が確保出来る(従業員の数とかにもよるが。あと、最初から黒字なんて、まず有り得ませんのでVCや銀行などからの出資などは重要)ので、無理に残業をする必要がない(利益率がどのくらいかにもよるが)。

 

三点目。無理に残業する必要がないので。

品質を高める為の努力もしやすい(平日夜と休日全部)ので、今よりも更に良いサービスを提供出来る確率が上がり、よって好循環で長続きしやすい。

といってもコレって、従業員の努力もゼロじゃダメ(当たり前だが)ですけどね。

あと、努力が「収益が上がる」努力である必要も。

 

まぁ、以下なんか見ると、残業が少ない(つまり高単価型)方を望んでいる人の方が多いんでしょうね。戦後直後ならともかく、比較的平和で且つ、成熟してる部分多数でしょうし、そういう人の方が大多数かと僕も思いますね。

 

www.lifehacker.jp

 

でも、現状は薄利多売が主流っぽいので、「横に広げる」しか無いでしょうね。リスクヘッジにもなりますし。といっても、「質が認識出来る(大体、オタクやマニアが多いですね。そのジャンルを壊す可能性もありますけど)」も捨てがたいのも確か(未来予測も出来ませんし)なので、「平行にやれば良いんじゃないの?」って思うんですけど、でも、あんまりそれを見ないという(苦笑)

 

あと、「高単価で稼ぎまくっているよ」で注意なのが、「確かに稼いではいるが、倫理観が怪しい」ケース。広告とレコメンド系が共通してますね。

で、この場合、「学ばない→理解出来ない→認識出来ない」で気付けないので、むしろ「消費者が学ばない方が稼げる」という(苦笑)

「倫理観をちゃんとしたら、あまり稼げなくなった」は、要するにモデルがその程度って事だと思いますけどね。なので、これも「横に広げる」か、「高単価で差別化が図れないか」検証するしかないですね。

といっても、完全に新規のビジネスモデルの場合は、しばらくは大丈夫でしょうけど、徐々に怪しくなっていくというのはあるでしょうね。

といっても、レコメンド系に関して(といっても広告も、そう変わらないか)は、「デフォルトはオプトアウトだが、ジャンル別(技術書はオプトインだが、生活用品はオプトアウトとか)にチェックボックスを分けてチェックしてもらうとか、基本観測外のジャンルの情報を、"毎日一回"・"週に一回"・"月に一回"毎に提供する」とか。あと、情報提供「する」情報と、「受け取りたい」情報も別にして。

要するに、「個人によって、どの辺がプライバシーと感じるかが違う」というのに対応と。

・・・一回、ネットリサーチ会社利用して、アンケート取ってみれば良いんじゃないかと思うんですねコレ。

個人的には、エロ系が分かりやすいですけど、情報提供「しない(基本的に勘違いされるので)」けど、でも情報は「受け取りたい」ので(笑)

というのがあるので、「きめ細かく」すると。

あと、以下の記事、最近読んで「最初はしっくりきた」んですけど、

その後、某所(ってFBだが)で議論した結果、

「どう頑張って設計したり実装しても、漏れたら個人と紐付くと思うんだが?」って結論になった次第でして、「統計処理」の詳細を知りたいなと。

 

海老澤澄夫の個人ブログ: レコメンドはプライバシーを侵害するか? 高木浩光氏への異論

 

なので、やるのは良いけど、前提として「オプトイン・オプトアウトは付けてね」っていう。

・・・リサーチ結果を、つくづく見たい所ですねココは。

 

あと、ここまで書いたので、いい加減、経営本を読みたい所ですね。

基本的に、「暴走を止めたり、スピードを若干緩めたりなどをするのが役割」でしょうし。

で、以下の本を読む限り、多少は「読む本も絞り込めそう」なので、

そうしましょうか。大体読んでいる暇がない(苦笑)

 

www.amazon.co.jp

 

次。

「薄利多売でも高単価でも良いけど、事業が失敗した(もしくはしそう)になったらどうすんだ?」は、「止めよう」。

で、ココで問題になるのが、サービスに愛着があると損切り出来なく、結構失敗率も高い」かなと。

以下に書いてますね。

 

d.hatena.ne.jp

 

でも無理ですよねぇ、大好きなもの止めるって。

これ逆に極論言っちゃえば、「俺、この商売"大っ嫌い"なんだけどさ、でも"有り得ない"ぐらい稼げるから、"仕方なく"やってるんだよね」が良いんでしょうけど、これは(精神力的に)難しい。

「愛着と客観性」がポイントだと思うんですけど、

「好きでやっている」のは良いけど、その時に「冷静な目でジャッジする」のも同時に行うと。

上記の、スーパージェネラリストの本の中でいう、「もう一人が、遠くから冷静に見ている」的な話ですね。かなりオカルトっぽいですけど(苦笑)

あと、もう一つの方法として、「あまりにも愛着があり過ぎて、結果として他人に全く理解されず、"どうして僕の事を誰も理解してくれないんだ!"と中二病っぽくなるが、しばらくして、何でなんだろう?ちょっと調べたり聞いたりしてみるかとなり、冷静に他人の感想などを聞ける」ケース。

分野によっては、僕はこっちですね(苦笑)

だから愛着も「有り得ないぐらいある」か、

もしくは「好きでいて且つ、客観的に見れる」なら、

損切りも出来るかなと。

 

 

最後に、今後の課題を書いて終わりにしましょう。

 

一つ目。中単価ビジネスって無いのかね?っていう。・・・これ、どっちかというと、BtoCよりBtoBな感がありますね。

 

二つ目。

「エンジニアって高単価な場合多いけど、でも薄利多売ビジネスで且つ、多角的に事業を展開してないと、一人当たりの手取りって減るし、相性悪いよね」

これは困った・・・が疲れたので、今日はココで終了にしましょう。