3

MySQL(workbench)、Perl、およびDBIの最新バージョンを使用しています。

それぞれ固有のサーバー上に2つの固有のデータベースがあります。Server1のDB1のtable1にクエリを実行し、配列にロードしてから、whileServer2のDB2のtable2にそのテーブルを挿入しています。

私は実際にテーブル1で選択を行っているので、これは直接のコピーではありません。

スクリプトを高速化するか、必要に応じてクエリを変更しようとしています。

私はバインドを使用していて、prepareステートメントをループの外に移動しました。これは本当に役に立ちました。ただし、table2 / db2 / server2に挿入するために160万回の呼び出しを行うことになり、膨大な時間(3100秒または呼び出しあたり約2〜3ミリ秒)を使用します。

whileDB2 table2をロードするためにループで使用される2つのサブ&insert2tempDataがあります。これは160万回呼び出され、DB1にクエリを実行してから2番目のサブを呼び出すために使用されるquery_dev_load_local_dbsです。

簡単にするために、この準備をループ内に残しましたが、私のコードでは、これはwhileループ内ではなく、このサブを呼び出すサブ内にあります。

sub insert2tempData {
    $query4tmpData = $Locdbh_NetCool->prepare ("INSERT INTO kpincpolldata.kpitempData
        (monitoredObjectId, monitoredInstId, pollTime, tdwTime, errorCode, value)
        VALUES(?, ?, ?, ?, ?, ?)");

    $query4tmpData->execute($row[0], $row[1], $row[2], $row[3], $row[4],
                            $row[5]);
    warn "Problem in retrieving results", $query4tmpData->errstr(), "\n"
        if $query4tmpData->err();

} #End sun insert to tempData

これは、server1、DB1、およびtable1のクエリに使用されるメインサブです。whileループを呼び出します

sub query_dev_load_local_dbs {
    $queryRemote = $Devdbh_NetCool->prepare("SELECT * FROM ncpolldata.pollData
                                   WHERE pollTime >= $STARTU AND pollTime < $ENDU
                                   AND monitoredObjectId = 1");

    $queryRemote->execute();

    while (@row = $queryRemote->fetchrow_array()) {

        #** Call to sub insert2tempData**
        &insert2tempData($Locdbh_NetCool);

        warn &print2log ("Problem in retrieving results"), $queryRemote->errstr(), "\n"
            if $queryRemote->err();
    } # End while

} # End sub query_dev_load_local_dbs
4

2 に答える 2

4

行をフェッチするたびにすべての戻り値のコピーを作成する必要がないため、fetchrow_arrayref()代わりに使用します。fetchrow_array()それは物事を少しスピードアップするはずです。もご覧くださいbind_columns

whileそれから私はあなたがループとで意味することを完全に理解していなかったprepareので、とにかく私は言います:サブから出て、それが一度d$query4tmpData=$Locdbh_NetCool->prepareできる別の場所に移動してからサブでprepareそれを再利用します。あなたはおそらくそれを持っています。


さらにいくつか:

  • あなたはいつもuse strictとすべきuse warningsです。my私はあなたの潜水艦に見えません。それらのプラグマを使用してください。彼らはあなたの人生を楽にします。
  • 「結果の取得に問題があります」を読み取れINSERTない場合に発行される警告。それが発生した場合、それはあなたを混乱させるかもしれません。
于 2012-07-06T20:15:37.673 に答える
4

上記で投稿したコードが、認識されているパフォーマンスの問題とは関係がない可能性があります。使用しているデータベースサーバーにその数の行を挿入するには、長い時間がかかる場合があります。これが私が見るものです:

  1. オフAutoCommitにすると、有効になります。

    毎回コミットすると、構成方法によってはinsertパフォーマンスに深刻な影響を与える可能性がありServer2ます。プロセス全体を1つのトランザクションにバッチ処理すると、処理が高速化される可能性があります。ただし、実際には、サーバーの構成方法、インデックスの作成方法などによって異なります。

    これにより、次のことが可能になります。

  2. 有能なDBAがお手伝いできるかもしれません。

    MySQLサーバーを管理しているのは誰かに確認し、トラブルシューティングに役立つかどうかを確認してください。誰が知っているか、彼らはあなたがコードで何も違うことをせずにあなたの問題を解決するのを助けるか、あなたがこのスクリプトを完全に廃棄すること さえ可能にするDBAツールさえ持っているかもしれません。

    あなたがDBAでない限り:

  3. あなたはDBAのためのStackExchangeサイトをいじくり回すかもしれません。

投稿したコードで修正すべき小さなことがいくつかあるかもしれませんが、データベースがボトルネックである場合、それは問題ではありません。ボトルネックを見つけてください!

于 2012-07-06T23:21:19.343 に答える