2017.03.24
Yii2の機能紹介とORMの注意点
こんにちは。次世代システム研究室のS.Iです。
今回はYii2 Frameworkを利用する際のパフォーマンスを意識した実装例と初心者がやってしまいがちなORM(Object Relational Mapping)を利用する際の注意点について紹介したいと思います。
ORMはとても便利で昨今のWeb開発では利用されるケースが非常に多いと思いますが、使い方を誤るといつの間にか大きなパフォーマンスの劣化や問題が発生することがあります。
実際にパフォーマンスの劣化が起きたケースのイメージです。
case 1.複数のデータを登録する。
下記は一件問題ないように見えますが、登録するデータの増加にともなって大きく遅延する可能性が高いです。
for ($i = 0; $i < 10; $i++) { $blog = Blog::create([ 'field1' => 'aaa', 'field2' => 'bbb' ]); $blog->save(); }
発行されるクエリは以下です。
INSERT INTO `blog` (`field1`, `field2`) VALUES ('aaa', 'bbb') INSERT INTO `blog` (`field1`, `field2`) VALUES ('aaa', 'bbb') ・・・・
10件、100件程度であれば問題がないものの、実際に問題のあったケースでは30000件くらいまで登録データが増加したところで問題が発生していました。データの増加が想定されるケースでは以下のような「multiple insert」を利用した実装にすることで効率的に処理し、このような問題を回避することができます。
Yii::$app->db->createCommand()->batchInsert(Blog::tableName(), ['field1', 'field2'], [ ['aaa','bbb'], ['aaa','bbb'], ])->execute();
発行されるクエリは以下です。
INSERT INTO `blog` (`field1`, `field2`) VALUES ('aaa', 'bbb'), ('aaa', 'bbb'), ('aaa', 'bbb') ・・・・
実際に1件から10万件で比較してみました。10万件程度でも、通常のinsertの430.23secに対して、multipleでは6.92secと約62倍も差がひらきました。件数が大きくなっていくと数百倍もの差が出てきます。
case 2.複数のデータを取得する。
今回のケースも一件問題ないように見えますが、扱うデータが増えていくようなケースの場合は取得したデータとModelのマッピングに時間がかかります。
Blog::find()->where(・・・)->all();
下記のように配列で返却することでModelオブジェクトに対するマッピングのオーバヘッドを回避することができます。
Blog::find()->where(・・・)->asArray()->all();
実際に1件から10万件で比較してみました。10万件程度でも、通常のobjectの10.05secに対して、arrayでは1.45secと約7倍も差がひらきました。
case 3.複数のデータを分割して取得することでメモリ消費量を抑える。
そのほかYii2では便利な機能が充実していてしっかり実装しないとバグを出してしまいそうな処理も簡単に実装できます。
該当するデータを指定した件数ごとに処理できます。ここでは100件の塊でループが回ります。
foreach (Blog::find()->batch(100) as $blogs) { ・・・ }
こちらはbatchとはことなり、まとめて取得したデータを1件づつ処理できます。
foreach (Blog::find()->each(100) as $blog) { ・・・ }
最後に
Yii2ではDB操作する上で便利な機能がありました。また、他のフレイムワークも同様ですが、ORMを利用する際は、実装する機能の以下を常に意識して実装方法を検討することでアクセスの増加やデータ量の増加があっても安定した運用を行うことができます。
・アクセス頻度はどれくらいか
・一度に取り扱うデータ量はどれくらいか
・データはどれくらい増加していくか
・処理の許容時間はどれくらいか
次世代システム研究室では、アプリケーション開発や設計を行うアーキテクトを募集しています。アプリケーション開発者の方、次世代システム研究室にご興味を持って頂ける方がいらっしゃいましたら、ぜひ 募集職種一覧 からご応募をお願いします。
グループ研究開発本部の最新情報をTwitterで配信中です。ぜひフォローください。
Follow @GMO_RD