0

1000行を含むcsvファイルを読んでいます。行ごとにクエリを実行します。クエリは次のとおりです。

$foobar = 
    SELECT foo1.ID
    FROM foo1
    INNER JOIN foo2 ON foo2.ID = foo1.ID
    LEFT JOIN foo3 bar1 ON bar1.ID = foo1.ID
    LEFT JOIN foo3 bar2 ON bar2.ID = foo1.ID
    WHERE foo1.Text LIKE :txt
    AND foo2.col1 = 31 AND bar1.col1 = 138 AND bar2.col1 = 271
    AND (bar1.col2 = "" OR bar1.col2 IS NULL) 
    AND (bar2.col2 = "" OR bar2.col2 IS NULL)

これについて Explainを実行し、検索対象の 100 行のみを返し、定数refを返しました。これは、インデックスを使用する高速であることを意味します。

今私のループには次のものがあります:

while ($line = fgetcsv($handle)){
    $foobar->execute(); 
    $data = $foobar->fetchAll(\PDO::FETCH_ASSOC);
    var_dump($data); echo '<br /><br />';
}

なぜ時間がかかるのですか?CSV ファイルには 1000 行しかなく、クエリで Explain を実行するだけで十分な速さのようです。

5〜10分後にタイムアウトしますが、それほど長くはかからないはずです。何が問題なのかわかりません。

foo3テーブルには700万件のレコードが含まれていることに注意してください。

4

4 に答える 4

1

スクリプトが実際に行末を検出できることを確認しましたか? そうでない場合は、試してください

ini_set('auto_detect_line_endings',TRUE);

また、データの長さを指定していないようです。次のようなものを試してください。

$line = fgetcsv($handle, 1000)

そして、PHPマニュアルをざっと見た後、最も使用されるアプローチはチェックすることです

while (($line = fgetcsv($handle, 1000)) !== FALSE)

\ を fetchAll ステートメントに追加したことにも気付きました。代わりにこれを試してください。

fetchAll(PDO::FETCH_ASSOC)

次のようにして、データを操作することもできます。

if($result = $stmt->fetchAll(PDO::FETCH_ASSOC))
{
    foreach($result as $res)
    {
        foreach($res as $key=>$val)
        {
            $temp[$key] = utf8_encode($val);
        }
        array_push($array, $temp);
    }
    var_dump($array);
    echo '<br /><br />';
}

一方、主な問題はクエリ自体にある可能性があります。たぶん、私があなたに与えたアプローチは、より速い方法になる可能性があります.

于 2013-03-07T15:39:57.877 に答える
0

クエリ「USES」がインデックスを作成するからといって、「高速である必要がある」という意味ではありません。速度は、「正しい」インデックスを使用できるかどうか、およびクエリが効率的に構築されているかどうかによって異なります。

たとえば、クエリでは次のものを使用します。

WHERE foo1.Text LIKE :txt

foo1および/またはfoo1.Textに多くの行があり、Textが大きく(つまり、TEXTタイプのフィールド)、:txtが%で始まる場合は、プライマリテーブルがインデックスを使用できないことを意味します。

また、必要なすべての結合インデックスが設定されていない可能性があります。たとえば、クエリから、フィールドfoo3.IDが主キーではないことが明らかです。

「なぜ時間がかかるのか」という質問に適切に答えるには、テーブルfoo1/2/3の構造に関する詳細情報が必要になります。

于 2013-03-07T15:34:50.790 に答える
0

コンソールでプロセスを開始してみてください。exec() の後に参照してください。プロセスは、プロセスの状態に関するデータを共有ストレージ (mysql/file/etc...) に置くことができます。

于 2013-03-07T15:27:45.037 に答える
0

行の 1 つだけが問題になっている可能性はありますか? これを CLI から実行することから始めます。出力を変更して、行のインデックスと実行にかかった時間を記録するだけにします。これは問題を明確にするのに役立ちます。

于 2013-03-07T16:54:05.107 に答える