ゴミ箱の中のメモ帳

まだ見ぬ息子たちへ綴る手記

ORMは重要だ

昨日にBottleのコードを読んでいたので今日はPeeweeのコードでも読もうかと思っていたのだが、そのPeeweeのコードでわからない部分を調べていると面白い記事を見つけた。

 その記事はこちら「http://redtower.tumblr.com/post/37364225033/sql-o-r」。

内容は非常に短く面白いので読んで欲しい。面白いと言っても「役に立つ」ではなく、「馬鹿げている」面白さだ。ぜひコメディとして読んで欲しい。

個人攻撃をするつもりはないが、そういった記事を読み、「確かめずに、確認せずに、思い込みで、憶測で、偏見で、先入観で、物事を判断したり、批判したりしてはいけない」ということを理解していただければと思う。

 

 ====
記事中での批判はこうだ。

select * from sales where deleted = false order by amount desc limit 10Sales.active().top(10).all()

 この二つが同義ではないのではないかというものだ。

 

記事中では具体的なORMの指定はないので、私がよく使うPeeweeを参考に確認してみよう。

確認用に簡単なモデルを書く。

import random
from peewee import SqliteDatabase, Model, IntegerField, CharField, BooleanField

db = SqliteDatabase(':memory:')

class Sales(Model):
    name = CharField(max_length=32)
    amount = IntegerField()
    deleted = BooleanField(default=False)

    class Meta:
        database = db

def insert():
    for i in range(10000):
        db.begin()
        Sales.create(
            **{
                'name': 'name_{0}'.format(str(i)),
                'amount': random.randrange(10000),
                'deleted': bool(random.randrange(1))
            }
        )
        db.commit()

if __name__ == '__main__':
    Sales.create_table()
    insert()

 

これでいいのかはわからないが、SQLを確認するだけであれば十分だろう。間違っていればご指摘いただきたい。

 

ではこれをPeeweeを使って同等のSQLになるか確認してみよう。

Sales.select().where(Sales.deleted == False).order_by(Sales.amount.desc()).limit(10)

 

これはPeeweeで書いたものなので先に例示されている表現方法とは異なるが、Peeweeの方がより生のSQLに近い表現方法だろう。

 

このPeeweeで書かれたチェーンが実際にはどういったSQLとして発行されるか確認してみる。Peeweeはsql()メソッドを使うことで実際に発行されるSQLを確認できる。

Sales.select().where(Sales.deleted == False).order_by(Sales.amount.desc()).limit(10).sql()

('SELECT "t1"."id", "t1"."name", "t1"."amount", "t1"."deleted" FROM "sales" AS t1 WHERE ("t1"."deleted" = ?) ORDER BY "t1"."amount" DESC LIMIT 10', [False])

 

どうだろうか。テーブル名が短縮の為に変えられていたり、文字列処理のためにクォートがついていたり、代入分がついていたりするがほぼ同義だろう。

 

とすると、

上記のSQLとO/Rマッパー疑似コードは等価ではない。


たぶん、上記のO/Rマッパーコードは Sales テーブルから全行をスキャンし、クライアントアプリケーションへネットワーク越しに転送する。アプリケーションは全行分のメモリを確保して全データを保持するが、このメソッドの処理で使うのは結局そのうち10行(しかもたぶんそのうちのごく一部のカラム値)だけだ。

 

と言うのは完全な間違いになる。全行分のメモリを確保していないし、もちろんindexを貼ればスキャンもされない。

これは確かに一見美しいのだが、これこそが「敷居を下げすぎて、dbの性質を分かってない人まで気軽にSQLをいじるようになった結果の悲劇」というのが後を絶たない原因でもある。

 

こういった確認をせずに文句を言えるという状態自体が「思考」の敷居を下げすぎているのではないだろうか。

 

プログラミングにしても、機械語アセンブリからC言語高級言語が生まれることでコンピュータの性質をわかっていない人まで気軽にプログラムをいじれるようになった結果の悲劇だろうか。実際に私もLLを使っている人間が、そのLLがC言語で書かれているということを理解させることに暇がかかったのを経験している。

ちなみに、むかし日本の岡崎市に、一秒に一回以上アクセスすると過負荷で落ちる上、アクセスした人が逮捕される、という冗談のようなwebサービスが実在したのだが、あれもこういうのが原因じゃないのかな。

 

これも完全な憶測だ。確認すれば原因の説明を読めるかと思うが、確認せず、自分の憶測のみで「原因じゃないかな」としている。この憶測は完全な間違いで実際はセッションの問題になる。

 

確かに先の例のようにLLが生まれたことでコンピュータが何かもわからないような人間がプログラミングをしていることは事実だ。だがそれの何が問題なのか。車だってセルモーターになった時点で「エンジンを回す」ということを理解している人間は少なくなっただろう。

面倒なこと、必要のないこと、見えなくてもいい場所は覆い隠してもいいのではないか。ORMが有ることで、SQLを理解していない人間もSQLを理解しないままそれを使うことが出来る。

その記事を書いている人間も、インターネットの仕組みやルータの仕組みを完全に理会しているのだろうか。そしてそのルータには回路やLEDなどのパーツが使われているし、ネットワーク上には様々なプロトコルのデータが流れ、そのデータもアルゴリズムに従い伝送されていく。

それを全て理解していない状態でインターネットを使うことは「敷居を下げている」と感じるのだろうか。

 

そしてあなたはそれらを全て理解しているのだろうか。

 

きっと、携帯電話のスペクトラム拡散についても理解していないのではないだろうか。(もちろんこれは憶測だ)