dav*_*and 13 mysql query-optimization
如果知道列的结果只有两个候选值,
ifnull(a, b) as a_or_b_1
Run Code Online (Sandbox Code Playgroud)
和
coalesce(a, b) as a_or_b_2
Run Code Online (Sandbox Code Playgroud)
会给出相同的结果.但哪个更快?在搜索时我发现了这篇文章,其中说ifnull更快.但这是我找到的唯一一篇文章.对此有何看法?
提前致谢 :)
mar*_*ton 13
我的观点是你应该根据你的用法进行基准测试.
我怀疑会有太大的不同.请记住,虽然单个基准测试可能表明一个稍微好一点,但数据随时间的变化可能会改变这一结果.
另请注意,COALESCE自1992年以来一直是标准SQL的一部分 - 我不确定IFNULL是否符合任何标准.
Adam Machanic有一篇关于对等效场景进行基准测试的好文章 - 性能:ISNULL与COALESCE(在SQL Server中).请注意获得有效测试的一些附带条件.
小智 5
由于从未给出 MySQL 的答案,因此这里有一个自定义过程,显示IFNULL
它比较大数据集慢约 10% COALESCE
。
CREATE PROCEDURE `compare_ifnull_coalesce`(max_var INT)
BEGIN
DECLARE COALESCE_BOTH_NOT_NULL INT(11);
DECLARE IFNULL_BOTH_NOT_NULL INT(11);
DECLARE COALESCE_FIRST_NULL INT(11);
DECLARE IFNULL_FIRST_NULL INT(11);
DECLARE i INT DEFAULT 1;
DECLARE StartDate DATETIME DEFAULT SYSDATE(3);
WHILE i <= max_var DO
IF (SELECT COALESCE('a', 'b') = 'b') THEN
SELECT 1;
END IF;
SET i = i + 1;
END WHILE;
SET COALESCE_BOTH_NOT_NULL = FLOOR(TIMESTAMPDIFF(MICROSECOND, StartDate, SYSDATE(3))/1000);
SET i = 1;
SET StartDate = SYSDATE(3);
WHILE i <= max_var DO
IF (SELECT IFNULL('a', 'b') = 'b') THEN
SELECT 1;
END IF;
SET i = i + 1;
END WHILE;
SET IFNULL_BOTH_NOT_NULL = FLOOR(TIMESTAMPDIFF(MICROSECOND, StartDate, SYSDATE(3))/1000);
SET i = 1;
SET StartDate = SYSDATE(3);
WHILE i <= max_var DO
IF (SELECT COALESCE(null, 'b') = 'a') THEN
SELECT 1;
END IF;
SET i = i + 1;
END WHILE;
SET COALESCE_FIRST_NULL = FLOOR(TIMESTAMPDIFF(MICROSECOND, StartDate, SYSDATE(3))/1000);
SET i = 1;
SET StartDate = SYSDATE(3);
WHILE i <= max_var DO
IF (SELECT COALESCE(null, 'b') = 'a') THEN
SELECT 1;
END IF;
SET i = i + 1;
END WHILE;
SET IFNULL_FIRST_NULL = FLOOR(TIMESTAMPDIFF(MICROSECOND, StartDate, SYSDATE(3))/1000);
SELECT
'both columns not null' AS `SCENARIO`,
CONCAT('Total milliseconds: ', COALESCE_BOTH_NOT_NULL) AS `COALESCE`,
CONCAT('Total milliseconds: ', IFNULL_BOTH_NOT_NULL) AS `IFNULL`
UNION
SELECT
'first column null' AS `SCENARIO`,
CONCAT('Total milliseconds: ', COALESCE_FIRST_NULL) AS `COALESCE`,
CONCAT('Total milliseconds: ', IFNULL_FIRST_NULL) AS `IFNULL`
;
END;
Run Code Online (Sandbox Code Playgroud)
然后,要获取结果,只需运行:
CALL compare_ifnull_coalesce(1000000);
Run Code Online (Sandbox Code Playgroud)
设想 | 合并 | 如果为空 |
---|---|---|
两列都不为空 | 总毫秒数:5175 | 总毫秒数:5687 |
第一列为空 | 总毫秒数:5185 | 总毫秒数:5793 |