[前][次][番号順一覧][スレッド一覧]

mysql:13950

From: <kinosita@xxxxxxxxxx>
Date: Wed, 09 May 2007 11:45:55 +0900
Subject: [mysql 13950] ストアドプロシージャを使うと遅くなる??


はじめまして。木下弘基と申します。

現在 MySQL 5.0.37 (WinXP) + C API で大量データを登録する
プログラムの開発に先立ち、簡単なサンプルを作り調査をしています。

プログラムの都合上データは動的に生成し、その都度登録する必要があるため、
ファイル経由(LOAD DATA LOCAL INFILE〜)ではなく、ストアドプロシージャで
実現しようと考えています。

ところが、素のINSERT文を繰り返し実行するよりも、ストアドプロシージャで
登録・呼び出す方が処理時間がかかり、プロペアドステートメントならば
素のINSERT文よりやや早いという結果が出てしまいました。

    素のINSERT文を10万回実行・・・・・33秒
    ストアドプロシージャ経由で登録・・・39秒
    プリペアドステートメントで登録・・・29秒

本来のプログラムで扱うデータの件数は数百万件、
INSERTでなくUPDATEの場合もあります。

お聞きしたい点は次の通りです。

Q1. (このサンプルデータにおいて)ストアドプロシージャの方が
    遅くなるのは、現時点でのMySQLの特性と考えるべきでしょうか?

Q2. Oracleの様に、ストアドプロシージャに対してバインド変数を
    受け渡す方法はありますか?
    (API、サンプルを見る限りこれは無さそうですが・・)

Q3. 他に何か高速に登録する手段は考えられるでしょうか?


実行した内容は次の通りです。

■ INSERT文そのままの実行例

    for (nCnt = 1; nCnt <= 100000; nCnt ++) {
        sprintf(cSQL, "INSERT INTO proc_tb VALUES (%d,'%s%d','%s');", 
            nCnt, "testdata", nCnt, "2007/05/08 10:10:18");
        mysql_query(mysql, cSQL);
    }

■ ストアドプロシージャ経由での実行例

    char *gcInsProc = 
        "CREATE PROCEDURE PROC_INSERT"
        "( IN in_no INT,"
        "  IN in_text TEXT,"
        "  IN in_day DATETIME"
        ")"
        "BEGIN"
        "   INSERT INTO proc_tb VALUES (in_no, in_text, in_day);"
        "END;";
...
    for (nCnt = 1; nCnt <= 100000; nCnt ++) {
        sprintf(cSQL, "call PROC_INSERT(%d,'%s%d','%s');",
            nCnt, "testdata", nCnt, "2007/05/08 10:10:18");
        mysql_query(mysql, cSQL);
    }

■ プリペアドステートメントでの実行例

char *gcInsPrepare = "INSERT INTO proc_tb VALUES (?, ?, ?)";

    stmt = mysql_stmt_init(mysql);
    mysql_stmt_prepare(stmt, gcInsPrepare, strlen(gcInsPrepare));

    memset(bind, 0, sizeof(bind));

    /* INTEGER PARAM */
    /* This is a number type, so there is no need
    to specify buffer_length */
    bind[0].buffer_type= MYSQL_TYPE_LONG;
    bind[0].buffer= (char *)&int_data;
    bind[0].is_null= 0;
    bind[0].length= 0;
...
    /* Bind the buffers */
    mysql_stmt_bind_param(stmt, bind);

    for (nCnt = 1; nCnt <= 100000; nCnt ++) {
        int_data = nCnt;
        sprintf(str_data, "%s%d", "testdata", nCnt);
        str_length = (unsigned long)strlen(str_data);
...
        mysql_stmt_execute(stmt);
    }

    mysql_stmt_close(stmt);

以上です。宜しくお願いします。



[前][次][番号順一覧][スレッド一覧]

->   13950 2007-05-09 11:45 [<kinosita@xxxxxxxxxx] ストアドプロシージャを使うと遅くなる??
     13951 2007-05-09 14:02 ┗[HIRATSUKA Sadao <hir]                                       
     13952 2007-05-09 16:40  ┗[<kinosita@xxxxxxxxxx]