Почему моя пользовательская функция MySQL работает намного медленнее, чем встраивание ее в запрос?

Я неоднократно использую этот запрос SELECT для чтения целых чисел без знака, представляющих адреса IPv4, и представления их как четвёртые строки с точками, читаемые человеком.

SELECT CONCAT_WS('.', 
  FLOOR(ip/POW(256,3)),
  MOD(FLOOR(ip/POW(256,2)), 256),
  MOD(FLOOR(ip/256), 256),
  MOD(ip, 256))
FROM ips;

С моими тестовыми данными для выполнения этого запроса требуется 3,6 секунды .

Я думал, что создает пользовательскую сохраненную функцию для int-> преобразование строк позволит упростить чтение запросов и разрешить повторное использование, поэтому я сделал следующее:

CREATE FUNCTION IntToIp(value INT UNSIGNED)
  RETURNS char(15)
  DETERMINISTIC
  RETURN CONCAT_WS(
    '.', 
    FLOOR(value/POW(256,3)),
    MOD(FLOOR(value/POW(256,2)), 256),
    MOD(FLOOR(value/256), 256),
    MOD(value, 256)
  );

С этой функцией мой запрос выглядит так:

SELECT IntToIp(ip) FROM ips;

но с моими тестовыми данными это занимает 13,6 секунды , чтобы выполнить.

Я ожидал, что это будет медленнее при первом запуске, так как есть дополнительный уровень косвенности, но почти в 4 раза медленнее кажется чрезмерным. Ожидается ли такая большая медленность?

Я использую из коробки MySQL Server 5.1 на Ubuntu 10.10 без изменений конфигурации.


Чтобы воспроизвести мой тест, создайте таблицу и заполните ее 1221 201 строкой:

CREATE TABLE ips (ip INT UNSIGNED NOT NULL);

DELIMITER //
CREATE PROCEDURE AddIps ()
BEGIN
  DECLARE i INT UNSIGNED DEFAULT POW(2,32)-1;
  WHILE (i>0) DO
    INSERT INTO ips (ip) VALUES (i);
    SET i = IF(i<3517,0,i-3517);
  END WHILE;
END//
DELIMITER ;

CALL AddIps();

21
задан Day 12 August 2011 в 00:05
поделиться