mysql,ifnull vs coalesce,哪个更快?

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

  • 来自在我的 Linux 笔记本电脑上的 Podman 容器中运行的 MariaDB 10.8.3 的结果 - 结果略有不同:两列都不为空:COALESCE:8824 与 IFNULL:8576。但是:COALESCE:第一列为空:8363 与 IFNULL:8811。来自 MySQL 的结果5.7.39 在我的 Linux 笔记本电脑上的 Podman 容器中运行:两列都不为空:COALESCE: 9613 vs IFNULL: 8673。第一列为空:COALESCE: 9076 vs IFNULL 9363。因此从这些测试来看,IFNULL 在“两列都不为空”的情况。 (2认同)