4

LOAD データを使用して MYSQL テーブルにデータをロードする必要があります。ロード中に、特定の条件に基づいてデータ フラグ列を適切な値に設定する必要があります。データ挿入はさまざまなスクリプトから発生する可能性があり、プロセスを集中化するために BEFORE INSERT トリガーを使用することを考えました。ここでの問題は、INSERT プロセスに時間がかかることです。サンプルとして、コマンド ラインから SOURCE コマンドを使用して、テスト データを配置するために 500 000 レコードのファイルを使用した場合、550 レコードのブロックは、空のテーブルから始まる挿入に約 19 秒かかります。約 2300 レコードの LOAD データを使用した場合 (これは、以前の挿入が失敗し、挿入されるデータが蓄積されない限り、定期的に発生する理想的な挿入です)、完了するまでに約 90 秒かかりました。

私が知りたいのですが:

  1. とにかくこのトリガーのパフォーマンスをそのまま改善できるか、または一般的にトリガーが遅いですか?

  2. 同じロジックを通常の SQL の処理に外部トリガーにシフトすると、パフォーマンスが向上します。(トリガー vs 通常の SQL)。申し訳ありませんが、いくつかの理由でこのシナリオをテストできませんでした。また、データ挿入が発生する可能性のあるスクリプトがたくさんあるため、これを避けたかったのです。

私のトリガーロジックは

CREATE TRIGGER `mydb`.`flag_data` BEFORE INSERT ON `mydb`.`mytable`

FOR EACH ROW BEGIN
    DECLARE threshold_val FLOAT;
    DECLARE time_upper_limit_1 FLOAT;
    DECLARE time_upper_limit_2 FLOAT;
    SET threshold_val = 400;
    SET time_upper_limit_1 = 4000;
    SET time_upper_limit_2 = 8000;

    SET new.data_flag=(SELECT CASE COUNT(*) WHEN 0 THEN 2 ELSE (SELECT CASE WHEN new.rf >@threshold_val THEN 5 WHEN new.rf < 0 THEN 5 ELSE (SELECT CASE WHEN MINUTE( new.rec_time) Mod 15 <> 0 THEN 1 ELSE new.data_flag END) END) END FROM vw_active_stn_list WHERE stn_id=new.stn_id);

    IF (new.data_flag = 0) THEN
        IF (new.rmode = 'H') THEN
            SET new.data_flag=(SELECT CASE WHEN COUNT(*)>0 THEN 2 ELSE 0 END FROM vw_mf_list WHERE stn_id=new.stn_id);
        ELSEIF (new.rmode = 'F') THEN
            SET new.data_flag=(SELECT CASE WHEN COUNT(*) > 0 THEN 4 ELSE (SELECT CASE WHEN ISNULL(TIMESTAMPDIFF(MINUTE,new.rec_time,Now()))=1 THEN 1 WHEN TIMESTAMPDIFF(MINUTE,new.rec_time,Now()) NOT BETWEEN 0 AND @time_upper_limit_1 THEN 1  ELSE 0 END ) END from stn_mf WHERE ((new.rec_time BETWEEN mf_start_time AND mf_end_time) OR (mf_start_time <= new.rec_time AND mf_end_time IS NULL)) AND stn_id=new.stn_id AND (stn_type='X' OR stn_type='Y'));
        ELSEIF (new.rmode = 'S' OR new.rmode = 'M') THEN
            SET new.data_flag=(SELECT CASE WHEN COUNT(*) > 0 THEN 4 ELSE (SELECT CASE WHEN ISNULL(TIMESTAMPDIFF(MINUTE,new.rec_time,Now()))=1 THEN 1 WHEN TIMESTAMPDIFF(MINUTE,new.rec_time,Now()) NOT BETWEEN 0 AND @time_upper_limit_2 THEN 1  ELSE 0 END ) END from stn_mf WHERE ((new.rec_time BETWEEN mf_start_time AND mf_end_time) OR (mf_start_time <= new.rec_time AND mf_end_time IS NULL)) AND stn_id=new.stn_id AND (stn_type='X' OR stn_type='Y'));
        END IF;
    END IF;
END
4

1 に答える 1

0

一括読み込みの場合、トリガーは遅くなります。あなたの場合、トリガーの代わりに標準 SQL に切り替えると効果的です。

トリガーは、挿入が少なく、頻度が低い場合に役立ちます。

于 2013-09-20T05:13:34.487 に答える