4

それ自体として非常に高速に実行されるクエリがありますが、そのクエリを関数の本体として使用すると、大幅な速度低下が発生します。これが私のテストケースです:

/******************* my function definition *********************/
DELIMITER $$

CREATE DEFINER=`root`@`%` FUNCTION `GetNextScheduleForProgram`(
  prog_id varchar(10)
) RETURNS varchar(10) CHARSET latin5
    DETERMINISTIC
BEGIN

  DECLARE scheduleid varchar(10);
  SET scheduleid =
  (
      SELECT sc.ScheduleID
        FROM Schedule sc
       WHERE sc.ProgramID=prog_id
         AND sc.StartDate BETWEEN now() and date_add(now(), interval 3 day)
    ORDER BY sc.StartDate ASC
       LIMIT 1

  );
  RETURN scheduleid;

END

そして、ここにクエリステートメントがあります。

  • まず、クエリはそれ自体として実行されます
  • 次に、関数は同じパラメーターで使用されます。
SET @ id1 =(SELECT sc.ScheduleID
              FROMスケジュールsc
             WHERE sc.ProgramID = '23860'
               AND sc.StartDate BETWEEN now()and date_add(now()、interval 3 day)
          sc.StartDateASCで注文
             制限1);
SET @ id2 = GetNextScheduleForProgram( '23860');

このテストでは、 @ id1はおよそ0.03秒で設定され@ id2は3.5秒(せいぜい2秒)で到着します。この驚くべきパフォーマンスヒットの原因は何だろうか。

この関数を別のストアドプロシージャで使用する必要があるため、ストアドプロシージャの各行を2〜3秒待つと、パフォーマンス全体が低下します。

この時点から誰かが私を改善するのを手伝ってもらえますか?

4

1 に答える 1

1

優れたテスト データのセットにアクセスできなければ、これほど多くのことをいじるのは困難です。変えてみることのできることについて、いくつかの提案 (咳はを推測します) しかありません。

関数パラメーターの文字型を明示的に宣言する

CREATE DEFINER=`root`@`%` FUNCTION `GetNextScheduleForProgram`(
  prog_id varchar(10) CHARSET latin5
...

関数でサブクエリを返すだけです

BEGIN
  RETURN
  (
    SELECT SQL_NO_CACHE sc.ScheduleID
    FROM Schedule AS sc
    WHERE sc.ProgramID = prog_id
      AND sc.StartDate BETWEEN NOW() AND DATE_ADD(NOW(), INTERVAL 3 DAY)
    ORDER BY sc.StartDate ASC
    LIMIT 1
  );
END

正確なテストを行うには、SQL_NO_CACHE を使用します

上記のコードで関数を作成でき、MySQL 5.1.45 で問題なく動作しました。正確なテストを行うには、クエリにこの行が必要です。そうしないと、返される数値を信頼して、クエリのコストがどれくらいかを知ることができなくなります。

RDBMS の神々にニワトリを生け贄に捧げる

今のところこれですべてです。この問題に興味があるので、もっと実験できるようにテスト データをどこかに貼り付けていただければ、喜んでそうします。

このファンキーに聞こえる問題について詳しく知りたい場合は、 MySQL チャット ルームで遠慮なく私に連絡してください。

于 2011-11-18T16:09:29.860 に答える