2

私は次のコードを持っています

function cron_day_counts()
{
    $subids = get_subids();
    array_push($subids, '');
    $from = '2011-10-19';
    $to = '2011-10-20';
    $days = days_interval($from, $to);
    $result_array = array();
    foreach ($subids as $subid)
    {
        for ($i = 0; $i < $days; $i++)
        {
            $date = date('Y-m-d', strtotime($from . '+ ' . $i . ' day'));
            $date_prev = date('Y-m-d', strtotime($date . '- 1 day'));

            $unique_id_query = mysql_query('SELECT (SELECT COUNT(DISTINCT `id`,`subid`) FROM `tb_stats` WHERE `date` <= \'' . $date . '\'' . (!empty($subid) && is_numeric($subid) ? ' AND `subid` = \'' . mysql_real_escape_string($subid) . '\'' : '') . ') - (SELECT COUNT(DISTINCT `id`,`subid`) FROM `tb_stats` WHERE `date` <= \'' . mysql_real_escape_string($date_prev) . '\'' . (!empty($subid) && is_numeric($subid) ? ' AND `subid` = \'' . mysql_real_escape_string($subid) . '\'' : '') . ') AS `unique_ids`');
            $unique_id_result = mysql_fetch_assoc($unique_id_query);

            $total_id_query = mysql_query('SELECT COUNT(DISTINCT `id`,`subid`) AS `total_ids` FROM `tb_stats` WHERE `date` = \'' . mysql_real_escape_string($date) . '\'' . (!empty($subid) && is_numeric($subid) ? ' AND `subid` = \'' . mysql_real_escape_string($subid) . '\'' : ''));
            $total_id_result = mysql_fetch_assoc($total_id_query);

            $unique_ip_query = mysql_query('SELECT (SELECT COUNT(DISTINCT `ip`,`subid`) FROM `tb_stats` WHERE `date` <= \'' . $date . '\'' . (!empty($subid) && is_numeric($subid) ? ' AND `subid` = \'' . mysql_real_escape_string($subid) . '\'' : '') . ') - (SELECT COUNT(DISTINCT `ip`,`subid`) FROM `tb_stats` WHERE `date` <= \'' . mysql_real_escape_string($date_prev) . '\'' . (!empty($subid) && is_numeric($subid) ? ' AND `subid` = \'' . mysql_real_escape_string($subid) . '\'' : '') . ') AS `unique_ips`');
            $unique_ip_result = mysql_fetch_assoc($unique_ip_query);

            $total_ip_query = mysql_query('SELECT COUNT(DISTINCT `ip`,`subid`) AS `total_ips` FROM `tb_stats` WHERE `date` = \'' . mysql_real_escape_string($date) . '\'' . (!empty($subid) && is_numeric($subid) ? ' AND `subid` = \'' . mysql_real_escape_string($subid) . '\'' : ''));
            $total_ip_result = mysql_fetch_assoc($total_ip_query);

            $global_query = mysql_query('SELECT COUNT(`id`) AS `global` FROM `tb_stats` WHERE `date` = \'' . mysql_real_escape_string($date) . '\'' . (!empty($subid) && is_numeric($subid) ? ' AND `subid` = \'' . mysql_real_escape_string($subid) . '\'' : ''));
            $global_result = mysql_fetch_assoc($global_query);

            $result = array();
            $result['subid'] = $subid;
            $result['date'] = $date;
            $result['unique_ids'] = $unique_id_result['unique_ids'];
            $result['total_ids'] = $total_id_result['total_ids'];
            $result['unique_ips'] = $unique_ip_result['unique_ips'];
            $result['total_ips'] = $total_ip_result['total_ips'];
            $result['global'] = $global_result['global'];

            $result_array[] = $result;
        }

    }
    //db insert
    return $result_array;
}

foreach および for ループからすべてのクエリを移動したいのですが、より速く動作すると思います。これを行う方法がわかりません。どんな助けでも大歓迎です。

4

4 に答える 4

0

すべてを取得しますsubid

テーブルごと
に、最小の日付と最大の日付の間でフィルタリングする単一のクエリを作成し、日付で
グループ化します

select subid, `date`, count(*) ... 
where subid IN($subids) and `date` between $smallest and $largest
group by subid, `date`

結果を繰り返し、subid、dateをキーとして、結果を配列に格納します

$mysql_results = array[$subid][$date] ...

最後に、次のように$subidsと日付を繰り返します。

foreach ($subids as $subid)
{
  for ($i = 0; $i < $days; $i++)
  {
     // set $date

     // check $mysql_results[$subid][$date] exists
  }
}

上記のようなものでは、必要なクエリは5つだけです。

5 x total days x size of the subids
于 2011-11-22T14:25:06.700 に答える
0

少なくとも、ループ内のクエリを毎日 1 つだけに結合する必要があります。したがって、5 日間の範囲の場合、クエリは 5 つになります。

または、日付範囲全体に対して単一のクエリを作成し、それをループの外に移動することもできます (ajreal で説明されているように)。次に、PHP を使用してすべてを整理します。

大規模なデータベースの場合、クエリを少し分割して、負荷とタイムアウトのリスクのバランスを取ります。また、コードの保守性を維持するのにも役立ちます。

また、データベースがどのように構造化され、インデックスが作成されているかも確認する必要があります。

著しく遅いですか?

また、array_push 関数は必要ですか? (あまり節約になるわけではありませんが、冗長に見えるのではないかと思っただけです)

本当に遅い場合は、使用方法に応じてプロセスを完全に再構築することを検討してください。

たとえば、毎日 00:01 に次のようなことを行うことができます。

このようにして、簡単なクエリを実行してデータを表示し、満足のいく数値を適切なパフォーマンスで操作できます。また、アーカイブすることで、不要な行を削除してクエリ テーブルを小さく保ちますが、後で必要に応じてログを保持します。

もちろん、これはデータベースのセットアップ方法に適合しない場合があります。

于 2011-11-22T15:51:09.790 に答える
-1

すべての をsubids取得し、述語を使用してフェッチを実行して、INすべての値を一度に取得します。それを配列に詰め込んでから、配列をループします。

于 2011-11-22T14:02:24.163 に答える
-1

MySQL または MySQLi 拡張機能の代わりに PDO::MySQL 拡張機能を使用します。このようにして、mysql 呼び出しの実行時間を大幅に短縮するクエリを準備できます。

于 2011-11-22T14:04:56.313 に答える