0

これは、サーバーのパフォーマンスに深刻な問題を引き起こし、サイトで「接続が多すぎます」という sql エラーを引き起こしているローテーション広告を管理する 1 つの php ファイルです。これがphpスクリプトです。私はphpの初心者なので、これを修正する方法について誰かが私に洞察を与えることができますか?

        <?

require("../../admin/lib/config.php");
// connect to database

mysql_pconnect(DB_HOST,DB_USER,DB_PASS);
mysql_select_db(DB_NAME);

$i = 1;
function grab()
{
    $getBanner = mysql_query("SELECT * FROM sponsor WHERE active='Y' AND ID != 999 AND bannerRotation = '0' ORDER BY RAND() LIMIT 1");
    $banner = mysql_fetch_array($getBanner);
    if ($banner['ID'] == ''){
        mysql_query("UPDATE sponsor SET bannerRotation = '0'");
    }   
    if (file_exists(AD_PATH . $banner['ID'] . ".jpg")){
        $hasAd = 1;
    }
    if (file_exists(BANNER_PATH . $banner['ID'] . ".jpg")){
        return "$banner[ID],$hasAd";
    } else {
        return 0;
    }
}

while ($i <= 3){
    $banner = grab();
    if ($banner != 0){
        $banner = explode(",",$banner);
        mysql_query("UPDATE sponsor SET bannerView = bannerView + 1 WHERE ID='$banner[0]'");
        mysql_query("UPDATE sponsor SET bannerRotation = '1' WHERE ID = '$banner[0]'");
        echo "banner$i=$banner[0]&hasAd$i=$banner[1]&";
        $i++;
    }
}

?>
4

3 に答える 3

2

mysqli が表示されません

問題は、データベースへの永続的なmysql_pconnect()接続を開き、実行の最後に閉じられないことです。また、接続が閉じられない場所で mysql_close() を呼び出していないためです。

そのすべてはマニュアルにあります: http://php.net/manual/en/function.mysql-pconnect.php

于 2012-10-27T17:12:35.723 に答える
1

クライアントにとって良いニュースは、前の開発者がプロ​​ジェクトを放棄したことです。彼がそれに取り組み続けていれば、彼はもっと多くのダメージを与えることができたでしょう.

  • このスクリプトは、ext/mysqli ではなく、ext/mysql を使用しています。ext/mysql は推奨されていないため、mysqli または PDO_mysql を使用することをお勧めします。

  • <?php短いタグ構文 ( ) ではなく、完全な PHP オープン タグ構文 ( ) を使用することをお勧めします<?。その理由は、すべての PHP 環境で短いタグを使用できるわけではなく、そのような環境にコードをデプロイすると、そのページを閲覧しているすべてのユーザーがそのコードを表示できるようになるためです。

  • このスクリプトはエラー チェックを行いません。データベースへの接続を試行した後、またはクエリを送信した後は、常にエラーを確認する必要があります。

  • を使用ORDER BY RAND() LIMIT 1してデータベースからランダムな行を選択する方法は、非効率的であることがよく知られており、最適化することはできません。テーブルの行数が大きくなると、このクエリがボトルネックになる可能性があります。ORDER BY RAND クエリの最適化に関する私の過去の回答、またはランダムな行の選択に関するJan Kneschke による素晴らしいブログを参照してください。

  • の使用に行き詰まったとしても、ORDER BY RAND()3 回呼び出して 3 つの異なるランダム スポンサーを取得する必要はありません。を使用するだけORDER BY RAND() LIMIT 3です。そうすれば、これまでに選ばれたことのないスポンサーを確実に獲得するために、bannerRotation に対する複雑でエラーが発生しやすい更新は必要ありません。

  • SELECT *この関数には必要ありませんが、使用するとすべての列がフェッチされます。

  • スポンサーが無作為選択の資格がない場合、つまり、active!='Y' の場合、または ID=999 の場合、別のテーブルに移動します。これにより、クエリが簡素化され、スポンサーのテーブルが小さくなり、クエリが高速になります。

  • UPDATEgrab() 関数にはWHERE句がないため、スポンサー テーブルのすべての行に適用されます。これが意図的なものだとは思いません。単一の行にのみ適用する必要があると思いますWHERE ID=$banner['ID']

  • このコードにはUPDATE、同じテーブルの同じ行に対する 2 つの連続したステートメントがあります。これらを組み合わせて、UPDATE2 つの列を変更する 1 つのステートメントにします。

  • grab() 関数は値をカンマで区切って追加し、返されるとすぐにその文字列を配列に分解します。関数が配列を返すことができることをプログラマーが知らないかのように。

  • を条件付きブロック$i++内に配置すると、このコードが無限ループで実行される可能性があります。つまり、このスクリプトは永久に実行できます。これらの数十が同時に実行されると、接続が不足します。

  • このコードはキャッシュを使用しません。広告バナーを提供するスクリプトはすべて高速である必要があり、データベースに対して複数の更新を行うのは十分に高速ではありません。読み取りと書き込みには、メモリ内キャッシュを使用する必要があります。一般的な選択肢はmemcachedです。

なぜこのクライアントは、独自の広告バナー サーバーをそれほど不慣れにコーディングしているのでしょうか? Google DFP Small Businessを使用してください。

于 2012-10-27T18:01:27.507 に答える
0

うわぁ!

grab()ループ内から呼び出されていますが、パラメータ化されていません。また、繰り返し呼び出す理由もないようです。

200% の高速化は簡単に実現できます。

于 2012-10-27T17:10:56.943 に答える