1

現在テーブルにある値を取得し、それらを「正規化」するために、MySQLでストアドプロシージャを作成しました。これは、ストアドプロシージャに渡される値ごとに、その値がすでにテーブルにあるかどうかを確認することを意味します。そうである場合は、その行のIDを変数に格納します。値がテーブルにない場合は、新しく挿入された値のIDが格納されます。次に、ストアドプロシージャは、IDを取得して、元の非正規化テーブルと同等のテーブルに挿入しますが、このテーブルは完全に正規化されており、主に外部キーで構成されています。

この設計での私の問題は、ストアドプロシージャが戻るまでに約10ミリ秒かかることです。これは、約1,000万件のレコードを処理しようとすると長すぎます。私の疑惑は、パフォーマンスが私が挿入をしている方法に関係しているということです。すなわち

INSERT INTO TableA 
 (first_value) 
VALUES 
 (argument_from_sp) ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id);

SET @TableAId = LAST_INSERT_ID();

「ONDUPLICATEKEYUPDATE」は、重複キーでは何も更新したくないので、行のid値を返すだけなので、ちょっとしたハックです。ただし、この手順を実行しなかった場合、「SET ...」ステートメントを実行しようとすると、LAST_INSERT_ID()関数が間違った値を返します。

MySQLでこれを行うためのより良い方法を知っている人はいますか?

4

2 に答える 2

2

私は戻って、代わりにこのケースを処理する関数を作成しました:

CREATE DEFINER=`root`@`%` FUNCTION `value_update`(inValue VARCHAR(255)) RETURNS int(11)
BEGIN
        DECLARE outId INT;
        SELECT valueId INTO outId FROM ValuesTable WHERE value = inValue;

        IF outId IS NULL THEN
                INSERT INTO ValuesTable (value) VALUES (inValue);
                SELECT LAST_INSERT_ID() INTO outId;
        END IF;

        RETURN outId;
END

前述のストアドプロシージャは、INSERTステートメント自体を実行する代わりに、これらの関数を呼び出します。パフォーマンス面では、上記の関数は私のセットアップでより高速です(ndbテーブルタイプを使用)。また、アプリケーションのすべての部分をベンチマークした後、これが引き起こしていたパフォーマンスの問題は、全体的なパフォーマンスのボトルネックのごく一部にすぎないことがわかりました。

于 2010-06-17T04:26:25.940 に答える
0

すでに一意の識別子を持っている場合、自動インクリメントの主キーが必要ですか?

于 2010-07-08T08:08:23.300 に答える