`

比较两种mysql递归tree查询效率-mysql递归tree

阅读更多

本文目的为对比mysql递归树两种查询方式效率。

比较两种mysql递归tree查询效率-mysql递归tree
比较两种mysql递归tree查询效率-mysql递归tree

 

工具/原料

  1. 1

    --创建表

     

    DROP TABLE IF EXISTS `t_areainfo`;
    CREATE TABLE `t_areainfo` (
     `id` int(11) NOT '0' AUTO_INCREMENT,
     `level` int(11) DEFAULT '0',
     `name` varchar(255) DEFAULT '0',
     `parentId` int(11) DEFAULT '0',
     `status` int(11) DEFAULT '0',
     PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=65 DEFAULT CHARSET=utf8;


     

  2. 2

    --初始数据

     

    INSERT INTO `t_areainfo` VALUES ('1', '0', '中国', '0', '0');
    INSERT INTO `t_areainfo` VALUES ('2', '0', '华北区', '1', '0');
    INSERT INTO `t_areainfo` VALUES ('3', '0', '华南区', '1', '0');
    INSERT INTO `t_areainfo` VALUES ('4', '0', '北京', '2', '0');
    INSERT INTO `t_areainfo` VALUES ('5', '0', '海淀区', '4', '0');
    INSERT INTO `t_areainfo` VALUES ('6', '0', '丰台区', '4', '0');
    INSERT INTO `t_areainfo` VALUES ('7', '0', '朝阳区', '4', '0');
    INSERT INTO `t_areainfo` VALUES ('8', '0', '北京XX区1', '4', '0');
    INSERT INTO `t_areainfo` VALUES ('9', '0', '北京XX区2', '4', '0');
    INSERT INTO `t_areainfo` VALUES ('10', '0', '北京XX区3', '4', '0');
    INSERT INTO `t_areainfo` VALUES ('11', '0', '北京XX区4', '4', '0');
    INSERT INTO `t_areainfo` VALUES ('12', '0', '北京XX区5', '4', '0');
    INSERT INTO `t_areainfo` VALUES ('13', '0', '北京XX区6', '4', '0');
    INSERT INTO `t_areainfo` VALUES ('14', '0', '北京XX区7', '4', '0');
    INSERT INTO `t_areainfo` VALUES ('15', '0', '北京XX区8', '4', '0');
    INSERT INTO `t_areainfo` VALUES ('16', '0', '北京XX区9', '4', '0');
    INSERT INTO `t_areainfo` VALUES ('17', '0', '北京XX区10', '4', '0');
    INSERT INTO `t_areainfo` VALUES ('18', '0', '北京XX区11', '4', '0');
    INSERT INTO `t_areainfo` VALUES ('19', '0', '北京XX区12', '4', '0');
    INSERT INTO `t_areainfo` VALUES ('20', '0', '北京XX区13', '4', '0');
    INSERT INTO `t_areainfo` VALUES ('21', '0', '北京XX区14', '4', '0');
    INSERT INTO `t_areainfo` VALUES ('22', '0', '北京XX区15', '4', '0');
    INSERT INTO `t_areainfo` VALUES ('23', '0', '北京XX区16', '4', '0');
    INSERT INTO `t_areainfo` VALUES ('24', '0', '北京XX区17', '4', '0');
    INSERT INTO `t_areainfo` VALUES ('25', '0', '北京XX区18', '4', '0');
    INSERT INTO `t_areainfo` VALUES ('26', '0', '北京XX区19', '4', '0');
    INSERT INTO `t_areainfo` VALUES ('27', '0', '北京XX区1', '4', '0');
    INSERT INTO `t_areainfo` VALUES ('28', '0', '北京XX区2', '4', '0');
    INSERT INTO `t_areainfo` VALUES ('29', '0', '北京XX区3', '4', '0');
    INSERT INTO `t_areainfo` VALUES ('30', '0', '北京XX区4', '4', '0');
    INSERT INTO `t_areainfo` VALUES ('31', '0', '北京XX区5', '4', '0');
    INSERT INTO `t_areainfo` VALUES ('32', '0', '北京XX区6', '4', '0');
    INSERT INTO `t_areainfo` VALUES ('33', '0', '北京XX区7', '4', '0');
    INSERT INTO `t_areainfo` VALUES ('34', '0', '北京XX区8', '4', '0');
    INSERT INTO `t_areainfo` VALUES ('35', '0', '北京XX区9', '4', '0');
    INSERT INTO `t_areainfo` VALUES ('36', '0', '北京XX区10', '4', '0');
    INSERT INTO `t_areainfo` VALUES ('37', '0', '北京XX区11', '4', '0');
    INSERT INTO `t_areainfo` VALUES ('38', '0', '北京XX区12', '4', '0');
    INSERT INTO `t_areainfo` VALUES ('39', '0', '北京XX区13', '4', '0');
    INSERT INTO `t_areainfo` VALUES ('40', '0', '北京XX区14', '4', '0');
    INSERT INTO `t_areainfo` VALUES ('41', '0', '北京XX区15', '4', '0');
    INSERT INTO `t_areainfo` VALUES ('42', '0', '北京XX区16', '4', '0');
    INSERT INTO `t_areainfo` VALUES ('43', '0', '北京XX区17', '4', '0');
    INSERT INTO `t_areainfo` VALUES ('44', '0', '北京XX区18', '4', '0');
    INSERT INTO `t_areainfo` VALUES ('45', '0', '北京XX区19', '4', '0');
    INSERT INTO `t_areainfo` VALUES ('46', '0', 'xx省1', '1', '0');
    INSERT INTO `t_areainfo` VALUES ('47', '0', 'xx省2', '1', '0');
    INSERT INTO `t_areainfo` VALUES ('48', '0', 'xx省3', '1', '0');
    INSERT INTO `t_areainfo` VALUES ('49', '0', 'xx省4', '1', '0');
    INSERT INTO `t_areainfo` VALUES ('50', '0', 'xx省5', '1', '0');
    INSERT INTO `t_areainfo` VALUES ('51', '0', 'xx省6', '1', '0');
    INSERT INTO `t_areainfo` VALUES ('52', '0', 'xx省7', '1', '0');
    INSERT INTO `t_areainfo` VALUES ('53', '0', 'xx省8', '1', '0');
    INSERT INTO `t_areainfo` VALUES ('54', '0', 'xx省9', '1', '0');
    INSERT INTO `t_areainfo` VALUES ('55', '0', 'xx省10', '1', '0');
    INSERT INTO `t_areainfo` VALUES ('56', '0', 'xx省11', '1', '0');
    INSERT INTO `t_areainfo` VALUES ('57', '0', 'xx省12', '1', '0');
    INSERT INTO `t_areainfo` VALUES ('58', '0', 'xx省13', '1', '0');
    INSERT INTO `t_areainfo` VALUES ('59', '0', 'xx省14', '1', '0');
    INSERT INTO `t_areainfo` VALUES ('60', '0', 'xx省15', '1', '0');
    INSERT INTO `t_areainfo` VALUES ('61', '0', 'xx省16', '1', '0');
    INSERT INTO `t_areainfo` VALUES ('62', '0', 'xx省17', '1', '0');
    INSERT INTO `t_areainfo` VALUES ('63', '0', 'xx省18', '1', '0');
    INSERT INTO `t_areainfo` VALUES ('64', '0', 'xx省19', '1', '0');


 

方式一:采用function获取所有子节点的id

  1. 1

    --查询传入areaId及其以下所有子节点

    DROP FUNCTION IF EXISTS queryChildrenAreaInfo;

    CREATE FUNCTION `queryChildrenAreaInfo` (areaId INT)

    RETURNS VARCHAR(4000)

    BEGIN

    DECLARE sTemp VARCHAR(4000);

    DECLARE sTempChd VARCHAR(4000);

     

    SET sTemp = '$';

    SET sTempChd = cast(areaId as char);

     

    WHILE sTempChd is not NULL DO

    SET sTemp = CONCAT(sTemp,',',sTempChd);

    SELECT group_concat(id) INTO sTempChd FROM t_areainfo where FIND_IN_SET(parentId,sTempChd)>0;

    END WHILE;

    return sTemp;

    END;

  2. 2

    --调用方式

    select queryChildrenAreaInfo(1);

    select * from t_areainfo where FIND_IN_SET(id, queryChildrenAreaInfo(1));

    END

 

方式二:采用临时表和存储过程完成

  1. 1

    -- 创建存储过程

    drop PROCEDURE showChildList;

    CREATE PROCEDURE showChildList (IN rootId INT)

    BEGIN

    CREATE TEMPORARY TABLE

    IF NOT EXISTS tmpList (

    sno INT PRIMARY KEY auto_increment,

    id INT,

    depth INT

    );

     

    DELETE FROM tmpList;

     

    CALL createChildList (rootId, 0);

     

    SELECT tmpList.*, t_areainfo.* FROM tmpList, t_areainfo

    WHERE

    tmpList.id = t_areainfo.id

    ORDER BY

    tmpList.sno;

    END;

     

    drop PROCEDURE createChildList;

    CREATE PROCEDURE createChildList (IN rootId INT, IN nDepth INT)

    BEGIN

    DECLARE done INT DEFAULT 0;

    DECLARE b INT;

     

    DECLARE cur1 CURSOR FOR SELECT id FROM t_areainfo WHERE parentId = rootId;

    DECLARE CONTINUE HANDLER FOR NOT FOUND

    SET done = 1;

     

    INSERT INTO tmpList VALUES (NULL, rootId, nDepth);

     

    OPEN cur1;

    FETCH cur1 INTO b;

     

    WHILE done = 0 DO

    CALL createChildList (b, nDepth + 1);

    FETCH cur1 INTO b;

     

    END WHILE;

    CLOSE cur1;

    END;

     

  2. 2

    -- 调用方式

    call showChildList(1);

    END

 

两种方式对比:

  1. 1

    --简易程度

    首先我们可以通过sql语句就可以看的出,方式二的代码量差不多是方式一的两倍,而且又是临时表又是游标的,极易出错。

    --效率对比

    可以通过图片可以看到,同样的查询结果,方式一仅仅需要0.044s既可以完成查询,而方式二则需要1.525s,效率远远低于方式一。

    END

 

结论:

  1. 1

    强烈推荐用方式一,当然你脑子不够数,用方式二我也管不着。

    END

 

注意事项

执行方式二是系统出报错,错误原因是因为没有指定控制递归调用层数上线,可以通过利用系统参数 max_sp_recursion_depth 来控制递归调用的层数上限。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics