Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么我的自定义MySQL函数比在查询中内联相同的函数慢得多?_Mysql_Performance_User Defined Functions - Fatal编程技术网

为什么我的自定义MySQL函数比在查询中内联相同的函数慢得多?

为什么我的自定义MySQL函数比在查询中内联相同的函数慢得多?,mysql,performance,user-defined-functions,Mysql,Performance,User Defined Functions,我反复使用这个SELECTquery来读取表示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->string转换将允许更易于阅读的查询并允许重用,因此我做了

我反复使用这个
SELECT
query来读取表示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->string转换将允许更易于阅读的查询并允许重用,因此我做了如下:

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倍似乎太多了预计会有这么慢吗?

我在Ubuntu10.10上使用现成的MySQL服务器5.1,没有任何配置更改


要复制我的测试,请创建一个表并填充1221201行:

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();
创建表ip(ip INT UNSIGNED NOT NULL);
分隔符//
创建过程AddIps()
开始
声明i INT无符号缺省POW(2,32)-1;
而(i>0)做什么
插入ips(ip)值(i);

设置i=IF(i使用此选项可以获得更好的性能:

CREATE FUNCTION IntToIp2(value INT UNSIGNED)
  RETURNS char(15)
  DETERMINISTIC
  RETURN CONCAT_WS(
    '.', 
    (value >> 24),
    (value >> 16) & 255,
    (value >>  8) & 255,
     value        & 255
  );

> SELECT IntToIp(ip) FROM ips;
1221202 rows in set (18.52 sec)

> SELECT IntToIp2(ip) FROM ips;
1221202 rows in set (10.21 sec)
在我的系统(四核(Fedora64位)上的2gB mysql 5.1实例)上,在添加测试数据后启动最初的SELECT需要4.78秒

编辑:预计会有这么慢吗?

是的,存储过程很慢,比解释/编译的代码慢很多。当您需要将某些数据库逻辑绑定到应用程序之外时,它们会很有用,因为它不属于特定的域(例如,日志/管理任务)。如果存储的函数不包含任何查询,最好使用您选择的语言编写实用程序函数,因为这样不会阻止重用(没有查询),而且运行速度会快得多


这就是为什么在这种特殊情况下,您应该使用INET_NTOA功能的原因,正如sanmai answer中建议的那样,该功能可用并满足您的需求。

不要重新发明轮子,使用:


这是否比相同调整的内联版本提供更好的性能?我并不(还)想要一个更快的函数,只是想了解为什么函数版本比
time mysql-u root test-e“从ips中选择IntToIp2(ip)”的内联版本的same7.4秒慢那么多>/dev/null
vs
time mysql-u root test-e“从ips中选择CONCAT_WS(',(ip>>24),(ip>>16)&255,(ip>>8)&255,ip&255)的1.3秒”>/dev/null
因此,这次函数调用开销超过了5倍。@Day nope直接查询速度要快得多;我假设存储函数天生比解释/编译代码慢,只是想向您展示一个更好的实现;顺便说一句,当存储函数/过程不包含任何查询时,总是这样当然,如果你真的需要在数据库中实现某些功能,也有一些用c/c++开发的UDF可以提高性能。当然,对于任何阅读对这个公认答案的评论的人来说,在这个特定的例子中,你应该使用内置的INET_NTOA函数在sanmai的answerWow.RTFM FTW.+1中建议将我的具体案例加快数英里,但guido回答了一般性的“为什么函数比内联慢”问题。与其他解决方案相比,使用此内置函数只需0.7秒:
time mysql-u root test-e“SELECT INET_NTOA(ip)从ips“>/dev/null
mysql> SELECT INET_NTOA(167773449);
    -> '10.0.5.9'