Я неоднократно использую этот запрос 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 5.1 на Ubuntu 10.10 без изменений конфигурации.
Для воспроизведения моего тестасоздайте таблицу и заполните 1 221 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();