1

mysqlテーブルからredisデータベースに大量のデータを取得しようとすると、少し問題が発生します。とにかく、しばらくすると「MySQLサーバーがなくなった」というエラーが表示されますが、その理由がわかりません。

編集:

または、ループを壊すコメント付きコードを使用すると、終了していないときに「終了」します。

これは私が使用するphpコードです(php-cliによって実行されます):

<?php
require 'Predis/Autoloader.php';
Predis\Autoloader::register();

mysql_connect('localhost', 'root', 'notcorrect') or die(mysql_error());
mysql_select_db('database_that_i_use') or die(mysql_error());
$redis = new Predis\Client();

//starting on 0 but had to edit this when it crashed :(
for($i = 3410000; $i<999999999999; $i += 50000) {
        echo "Query from $i to  " . ($i + 50000) . ", please wait...\n";
        $query = mysql_unbuffered_query('SELECT * FROM table LIMIT ' . $i . ', 50000')or die(mysql_error());
        // This was code I used before, but for some reason it got valid when it wasn't supposed to. 
        /*if(mysql_num_rows($query) == 0) {
                echo "Script finished!\n";
                break;
        }*/
        while($r = mysql_fetch_assoc($query)) {
                $a = array('campaign_id' => $r['campaign_id'],
                           'criteria_id' => $r['criteria_id'],
                           'date_added' => $r['date_added'],
                );

                $redis->hmset($r['user_id'], $a);
                unset($a);
                usleep(10);
        }
        echo "Query completed for 50000 rows..\n";
        sleep(2);
}



unset($redis);
?>

私の質問は、これをより良くする方法です。なぜクラッシュするのか、真剣にわかりません。私のサーバーはかなり古くて低速で、この大量のデータを処理できない可能性がありますか?これは、実際の本番環境に切り替える前の単なるテストサーバーです。

注目に値するのは、スクリプトが30分ほど正常に実行され、数値が高くなるとスクリプトが非常に遅くなるのは制限ステートメントである可能性があることです。それでは、これを行う簡単な方法はありますか?今日はすべてのデータを転送する必要があります!:)

前もって感謝します。

編集:実行例:

Query from 3410000 to  3460000, please wait...
Query completed for 50000 rows..
Query from 3460000 to  3510000, please wait...
Query completed for 50000 rows..
Query from 3510000 to  3560000, please wait...
Query completed for 50000 rows..
Query from 3560000 to  3610000, please wait...
MySQL server has gone away

編集:

テーブルは約500万行のデータで構成され、約 サイズは800MBです。しかし、後でさらに大きなテーブルに対して同様のことを行う必要があります。

4

1 に答える 1

1

まず、別のスクリプト言語を使用することをお勧めします。Perl、Python、Rubyなど、この種のスクリプトを実行するにはPHPよりも優れています。

mysql接続が失われる理由についてはコメントできませんが、パフォーマンスを向上させるには、mysqlサーバーとredisサーバーで可能な限り多くのラウンドトリップを排除する必要があります。

その意味は:

  • バッファリングされていないクエリではなく、バッファリングされたクエリを使用する必要があります(クエリでLIMITが使用されている場合)

また

  • LIMITを使用してmysqlクエリを反復することはできません。これは、2次の複雑さが得られるのに対し、線形である必要があるためです。PHPで回避できるかどうかはわかりませんが。

  • Redisに送信したコマンドをパイプライン処理する必要があります

Predisを使用したパイプラインの例を次に示します: https ://github.com/nrk/predis/blob/v0.7/examples/PipelineContext.php

実際、これに本当にPHPを使用する必要がある場合は、mysqlデータをテキストファイルにエクスポートし(たとえば、「select into outfile」を使用)、ファイルを読み取り、パイプラインを使用してデータをRedisにプッシュします。

于 2012-04-16T17:01:59.657 に答える