Yiiの高速カウンター

Yii PHPフレームワークのリリース1.1.8では、CActiveRecordクラスにカウンターを操作するための追加メソッド、つまりsaveCountersが追加されました。 おそらくあなたの多くはリリース発表で彼について読んだでしょう。 カットの下で、そのクールさとは何か、なぜそれを使用する価値があるのか​​を説明します。 おそらく読んだ後、コードをリファクタリングするために実行します。



saveCountersの外観に関するアナウンスを読んだ後、既存の機能の単なるラッパーであると思いました。 メソッドのドキュメントも、パフォーマンスを改善するためのマニュアルも、速度に関するその機能については何も述べていません。 一般的に、読んで忘れていました。



多くの場合、一部のデータを定期的に集約する必要があるタスクがあります。 私の場合、それは単純なバナーのひねりでした。 バナーが表示されると、生のテーブルに行が追加されました。 クラウンでスクリプトが呼び出されました。スクリプトはサイクルで生データを実行し、特にバナーのインプレッション数を増やしました。 ループ内には次のコードがあります。

$banner->hits++; $banner->save();
      
      





すべてがうまくいきましたが、負荷とともに問題が増え始めました。 クラウンスクリプトは時間切れになり、タイムアウトによって低下し始めました。 プロファイリングと科学的調査の過程で、スクリプトロジックが変更され、上記のコードフラグメントを除くすべてが変更されました。 彼は疑う余地がありませんでした。 結局のところ、無駄でした。



そのとき、特別なsaveCountersメソッドを思い出しました。 コードをこれに置き換えると、スクリプトのパフォーマンスに関するすべての問題が解決されました。

 //    " "=>"  " $banner->saveCounters(array('hits'=>1));
      
      





この問題の解決策に驚いたので、メソッドのパフォーマンスを比較し、コードを調べることにしました。

テスト環境:core2 6420、ram 3gb、標準設定のZend Server CE 5.5。

テストコード:

 $start = microtime(true); for($i=0;$i<1000;$i++) { $banner->hits++; $banner->save();  $banner->saveCounters(array('hits'=>1)); } echo microtime(true)-$start;
      
      





いくつかの測定が実行され、結果は次のとおりです。

-()〜39秒保存

-saveCounters()〜23秒

つまり saveCountersは最大41%高速です!



それで、秘密は何ですか?


すべてが非常にシンプルであることが判明しました。 saveCounterメソッドのコードは単純ですが、それはポイントではありません。 主なことは、これらのメソッドからのSQLクエリの内容です。



save()メソッドは、テーブル内のすべてのフィールドを含む重いクエリを生成します。

このようなもの:

 UPDATE `banners` SET `id`=1, `name`='test', `info`='long-long description', `hits`=3560, `iduser`='2', `created_at`='2012-02-17 13:14:02', ... WHERE `banners`.`id`=1
      
      





saveCounters()メソッドは、この操作に最適なリクエストを生成します。

 UPDATE `banners` SET `hits`=`hits`+1 WHERE `banners`.`id`=1
      
      





これがパフォーマンスの秘密です。



この情報があなたにとって有用であり、あなたのウェブアプリケーションが少し速くなることを願っています。



All Articles