limit を使うか where を使うか問題
今日学んだこと
$table->find()->limit()
は、使いドコロが肝心ということ。
limit を使うべきなのは、paginate のように、データの内容によらずDBからデータを抽出したい時。 limit を使って条件判定するべきではない。
limit を使うか where を使うか問題
例:
Table名前 : 商品タグ
id | tag | created |
---|---|---|
1 | 売れ筋 | 2016-07-01 |
2 | 期間限定価格 | 2016-07-08 |
3 | 芸能人が着用 | 2016-07-10 |
4 | 新着 | 2016-07-12 |
みたいなテーブルを考える
4の新着は、基本的には商品が到着したタイミングでしか使わない。
だから普段見えていて欲しい情報を表示するには、
$table->find()->order(['id' => 'asc'])->limit(3);
というコードを書けば問題ない。
ただ、この書き方が議論になった。
$table->find()->order(['id' => 'asc'])->where(['tag !=' => '新着'] );
と書いたほうがいいという宗教の人が現れたからだ。
この宗教家が!!!と思ったが、
社内で最もDBに詳しいと言われる人に聞いてみたところ、後者の書き方のほうがいいと言われた。
理由は、
1. 新しいtag が追加された時に困る から
2. DBの id は、基本意味がないものとして取り扱うから
というものであった。
理由1 は自明である。
上記のコードでは、レコードが増えた時に対応できない。
さすがに素人に毛が生えた程度の僕でもこんなミスはしない。
では、理由2は?
この理由を考えるにあたって、普段人がどのような気持ちでレコードを取り扱っているかという精神論が大切になる。
気持ちを言語化する。
それは、自然キーという考え方、サロゲートキーという考え方に起因する問題だ。
キーとは?
情報を一意に特定するために用いられる目印のこと。
自然キー、サロゲートキー、複合主キーなどがある。
自然キーとは?
自然に作られたキーのこと。
例えば、人名などがそれにあたる。
人の名前は自然発生的につけられる(と仮定する)が、
同姓同名の人がいなければ、人名で人を一意に特定することができる。
この場合、人名は自然キーの役割を果たしているといえる。
自然キー派の主張
複合主キーとは?
自然キーの派生版のような感じ。
自然キーのところに書いたが、同姓同名の人がいる場合もある。
そのような場合に、もう少し情報を足すことによって人を一意に特定できることがある。
xx さんという同姓同名のひとがいた場合でも、
○○県からお越しの xx さんといえば、人を特定できるという考え方だ。
これを 複合主キーという。
サロゲートキーとは?
フレームワーク等により割り振られる、意味を持たないキーのこと。
1から始まり、被りなく1 ずつ増加していく値が用いられる。
サロゲートキー派の主張
本題
本当に簡単な説明で済ませてしまったが、 上記が自然キーとかサロゲートキーとか言われているものだ。
上記のテーブルの例で用いられているid は、サロゲートキーだ。
すなわち、id の値はフレームワークが勝手に振った値であり、意味が無い。
つまり、 id 4
に 新着
と 2016-07-12
が割り当てられているということには意味が無い。
一方、 新着
と 2016-07-12
が同一レコード内に存在するということには意味がある。
これらを端的に並べると、以下のようになる。
レコードの縦の並び順には意味が無い。 レコード内のサロゲートキーには意味が無い。 サロゲートキー以外の値が同一レコードに存在していることには重要な意味がある。
すなわち、
$table->find()->order(['id' => 'asc'])->limit(3);
というコードを書くと、何をしているのかがわからないのだ。
何をしているのかがわからないということは、
勝手に順番を変えられる可能性があったり(そんなことはまずないと思うが)
メンテナンシビリティが下がったり(主な問題はこれだと思う)する可能性があるということだ。
だから、一番上で書いたように、
$table->find()->order(['id' => 'asc'])->limit(3);
と書くよりも、
$table->find()->order(['id' => 'asc'])->where(['tag !=' => '新着'] );
と書くほうがずっといい ということになる。
説明が難しくて、うまく伝わったか不安だが、
少しでも同じことで悩む人が減るといいと願っています。
補足
本文中で何度か縦の並び順には意味が無い と書いたが、実は横の並び順にも意味はない。
意味があるのは、同一レコードの特定のカラムに入った情報だけだ。
ただ、長くなりそうなので続きは次回にしようと思う。
一言
ブログは1ポモドーロと決めていたが、早速ルールを破ってる。
諸言
目的
昨日の夜突発的にはてなブログを開設したので、目的も何もない。 つまり、書くことが何もない。
なので、TIL (Today I Learned ) を書こうと思う。 ダイアリーに書けば? とかはなし。
過去のブログ遍歴
実は今まで過去何度かブログに挫折したことがある。
mixi
大学に入ったばかりで右も左もわからなかった頃。 mixi というのが流行ってると聞いて なるほど! と思って始めた。 最初の1年ぐらいは継続的に更新していたが、 パタリと更新するのをやめてしまった。seesaa アフィリエイトってなんだろう?とか思っていた頃。 ポッドキャスト番組を始めて(50回ぐらい続いた。) けっこう色々な人に見てもらってた頃。 毎日ポッドキャストをするのは正直つらかった。 ポッドキャストの終了と同時に終了。
サクラのレンタルサーバ + WordPress 半年ほど前、今の会社に入社する直前に始めた。 ちょこちょこ更新はしていたが、全記事で10個ぐらい。 大学を辞める理由とかを長々と書いた思い出。 たぶん良い文章だったんだろうと思う。 4000の論文を書くのはとても大変なのに、 自分の思いを4000字書くのは超簡単だということに驚いた思い出。 今もネットのどこかに転がっていると思う。 早く契約を解除しないと来年もレンサバ代を払ってしまう。 急ごう。
始めた理由
うっかり口が滑ったから。 この業界では、一部にGithub にTIL を上げるという文化があるらしいが、 僕はそれをやってもうまく続かなかった。 というか、はじめてもいない。
昨日、先輩社員的な人たちとの面談があった。 その時の会話
先輩社員O 「TIL やれば?」
僕 「いやー、一歩が踏み出せなくてー」
僕(心の声) 「絶対いやだ。」
先輩社員O 「そっかー。残念だなー。」
僕 笑顔
僕(心の声) 「この先輩怖いって聞いてるし怒られるかな?」
先輩社員O 「まあでも、TIL なんかよりもブログ書くのが一番なんだけどね。」
僕(心の声) 「ブログならやったことある!楽勝じゃん!」
僕 「じゃあブログ書きます!」
先輩社員O 「あ、言った」
先輩社員S 「よし、聞いた」
先輩社員Y 「OK、メモった」
という感じ。 まあどこまで続くかわからないけど、やってみる。
ルール
- 25分(1ポモドーロ)で書く
- MarkDown 記法で書く(今後変更されるかも)
- プログラミング関係の話は極力Qiita に書く
- 基本的に今日学んだことを書く -> 書き溜めをしない!
一言
頑張る!
first commit
うっかり口を滑らせてしまったので、ブログを作った。
やると決めたらやる!