Проблема производительности хранимой функции Mysql - PullRequest
4 голосов
/ 17 ноября 2011

У меня есть запрос, который выполняется очень быстро, но сам по себе, когда я использую этот запрос в качестве тела функции, он сильно замедляется.Вот мой тестовый пример:

/******************* 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 Schedule sc
             WHERE sc.ProgramID='23860'
               AND sc.StartDate BETWEEN now() and date_add(now(), interval 3 day)
          ORDER BY sc.StartDate ASC
             LIMIT 1);
SET @id2 = GetNextScheduleForProgram('23860');

В этом тесте @ id1 устанавливается примерно за 0,03 секунды , тогда как @ id2 приходит за 3,5 секунды (2 секунды приЛучший).Интересно, что вызывает это замечательное снижение производительности.

Мне нужно использовать эту функцию в другой хранимой процедуре, поэтому ожидание 2-3 секунды для каждой строки в хранимой процедуре убивает мою общую производительность.

Кто-нибудь может помочь мне улучшить с этого момента?

1 Ответ

1 голос
/ 18 ноября 2011

Без доступа к хорошему набору тестовых данных с этим сложно поиграться.У меня есть только несколько предложений (* кашель * догадки * кашель *) о вещах, которые вы можете попробовать изменить.

Явно объявите тип символа для параметра функции

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.Для точного тестирования вашим запросам нужна эта строка, или вы не можете доверять полученным номерам, чтобы выяснить, насколько дороги ваши запросы.

Пожертвуйте курицу божествам СУБД

Это все, что у меня есть на данный момент - мне любопытно с этой проблемой, так что если вы захотите вставить куда-нибудь данные тестирования, чтобы я мог больше экспериментировать, я бы хотел это сделать.

Не стесняйтесь пинговать меня в MySQL-чате , если вы хотите пережевывать эту странно звучащую проблему.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...