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 

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

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

Source: https://habr.com/ru/post/J138534/


All Articles