Mysql 嵌套集模型优化

Mysql 嵌套集模型优化,mysql,model,nested,set,Mysql,Model,Nested,Set,我有一个网站,包含约10万页(200-300个并发用户)。每个页面在mysql InnoDB表中都有自己的记录-页面: 如您所见,我使用嵌套集模型来显示页面的层次结构等。。除了INSERT、UPDATE和DELETE语句的性能外,一切似乎都很好。将页面从一个父级移动到另一个父级非常慢,有时需要约30秒(!!) 硬件:四核Q6600(4x2.40+GHz),4GB RAM 谢谢你的建议 编辑: 表页如下所示: CREATE TABLE `page` ( `page_id` int(10) un

我有一个网站,包含约10万页(200-300个并发用户)。每个页面在mysql InnoDB表中都有自己的记录-页面:

如您所见,我使用嵌套集模型来显示页面的层次结构等。。除了INSERT、UPDATE和DELETE语句的性能外,一切似乎都很好。将页面从一个父级移动到另一个父级非常慢,有时需要约30秒(!!)

硬件:四核Q6600(4x2.40+GHz),4GB RAM

谢谢你的建议

编辑:

表页如下所示:

CREATE TABLE `page` (
  `page_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `page_parent` int(10) unsigned DEFAULT NULL,
  `left_id` int(11) NOT NULL,
  `right_id` int(11) NOT NULL,
  `page_module` smallint(5) unsigned NOT NULL,
  `page_connector` smallint(5) unsigned NOT NULL,
  `page_subject` varchar(255) NOT NULL,
  `page_title` varchar(255) DEFAULT NULL,
  `page_path` varchar(255) NOT NULL,
  `page_text` int(10) unsigned DEFAULT NULL,
  `page_children` mediumint(8) unsigned NOT NULL,
  `page_depth` smallint(5) unsigned NOT NULL DEFAULT '0',
  `page_content` tinyint(3) unsigned NOT NULL,
  `page_publish` tinyint(1) unsigned NOT NULL DEFAULT '1',
  `page_published` datetime DEFAULT NULL,
  `page_unpublished` datetime DEFAULT NULL,
  `page_time` int(10) unsigned NOT NULL,
  `page_edit_time` int(10) unsigned NOT NULL,
  `page_delete` tinyint(1) unsigned NOT NULL DEFAULT '0',
  `page_richtext` tinyint(1) unsigned NOT NULL DEFAULT '0',
  `page_cache` tinyint(1) unsigned NOT NULL DEFAULT '1',
  `page_template` varchar(255) NOT NULL,
  PRIMARY KEY (`page_id`),
  KEY `page_parent` (`page_parent`),
  KEY `left_id` (`left_id`),
  KEY `right_id` (`right_id`),
  KEY `page_depth` (`page_depth`),
  KEY `page_path` (`page_path`),
  KEY `page_connector` (`page_connector`),
  KEY `page_text` (`page_text`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

作为第一步,确保您有单独的索引

页码号

家长

左id,右id

右图

编辑

从page_parent=0的页面中选择MAX(right_id)进入DSTLefID

通过在(第\页父项,右\ id)上设置和索引,可以加快上述查询的速度


除此之外,如果不更全面地了解系统并可能修改其工作方式,我真的不能提出太多建议。

你能发布表的结构吗,它会有帮助,特别是索引。啊,嵌套集合的乐趣——也许有了好的旧邻接列表,事情会简单一些??我添加了表格的完整结构。也许有一种不同的方法可以将页面从一个节点移动到另一个节点?我有以下索引:page\u id、page\u parent、left\u id、right\u id。我应该在(left\u id、right\u id)和right\u id上设置单独的索引吗?您会多次出现“WHERE left\u id=-srcRightId;”,所以我会说您需要(left\u id、right\u id)和right\u id作为两个单独的索引。您是否尝试过执行单个查询以查看哪个(如果有的话)特别慢?当我们必须更新大量数据时,表“page”上的每个UPDATE语句都很慢,MySQL必须更新它们的表索引:/n无论如何,这是嵌套集模型的缺点:(工作正常,直到我们必须插入新记录作为某个节点的子节点。
 CREATE PROCEDURE `PAGE_MOVE`(IN `pageSrc` INT, IN `pageDst` INT)
    LANGUAGE SQL
    NOT DETERMINISTIC
    CONTAINS SQL
    SQL SECURITY DEFINER
    COMMENT ''
BEGIN
    DECLARE srcLeftId INT;
    DECLARE srcRightId INT;
    DECLARE dstLeftId INT;
    DECLARE dstRightId INT;
    DECLARE width INT;

    SELECT left_id, right_id, right_id - left_id + 1
    INTO srcLeftId, srcRightId, width
    FROM page
    WHERE page_id = pageSrc;

    IF pageDst > 0 THEN
        SELECT left_id, right_id
        INTO dstLeftId, dstRightId
        FROM page
        WHERE page_id = pageDst;
    ELSE
        SELECT MAX(right_id) INTO dstLeftId FROM page WHERE page_parent = 0;
        SET dstRightId = dstLeftId + 1;
    END IF;

    IF dstLeftId > 0 THEN

        UPDATE page SET page_children = page_children - (width / 2)
        WHERE left_id < srcLeftId AND right_id > srcRightId;

        UPDATE page SET page_children = page_children + (width / 2)
        WHERE left_id <= dstLeftId AND right_id >= dstRightId;

        /**
         * Set nagative values to left_id and right_id (temporary)
         */
        UPDATE page
        SET left_id = -left_id, right_id = -right_id
        WHERE left_id >= srcLeftId AND right_id <= srcRightId;

        UPDATE page SET left_id = left_id - width WHERE left_id > srcLeftId;
        UPDATE page SET right_id = right_id - width WHERE right_id > srcRightId;

        UPDATE page SET left_id = left_id + width
        WHERE left_id >= IF(dstRightId > srcRightId, dstRightId - width, dstRightId);

        UPDATE page SET right_id = right_id + width
        WHERE right_id >= IF(dstRightId > srcRightId, dstRightId - width, dstRightId);

        SET @diff = IF(dstRightId > srcRightId, dstRightId - srcRightId -1, dstRightId - srcRightId - 1 + width);

        UPDATE page
        SET left_id = -left_id + @diff,
             right_id = -right_id + @diff
        WHERE left_id <= -srcLeftId AND right_id >= -srcRightId;
        /**
         * Set parent_id and page_depth
         */
        UPDATE page SET page_parent = pageDst, page_depth = GET_PAGE_DEPTH(page_id) WHERE page_id = pageSrc;

        /**
         * Update page_depth in children's nodes
         */
        IF width > 2 THEN

            SELECT left_id, right_id
            INTO srcLeftId, srcRightId
            FROM page
            WHERE page_id = pageSrc;

            UPDATE page
            SET page_depth = GET_PAGE_DEPTH(page_id)
            WHERE left_id >= srcLeftId AND right_id <= srcRightId;      
        END IF;


    END IF;
END
CREATE FUNCTION `GET_PAGE_DEPTH`(`pageId` MEDIUMINT UNSIGNED)
    RETURNS smallint(6)
    LANGUAGE SQL
    DETERMINISTIC
    READS SQL DATA
    SQL SECURITY DEFINER
    COMMENT ''
BEGIN
    RETURN (
        SELECT COUNT(*) -1 AS depth
        FROM page AS parent
        INNER JOIN page AS node ON node.page_id = pageId
        WHERE node.left_id BETWEEN parent.left_id AND parent.right_id
    );
END
CREATE TABLE `page` (
  `page_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `page_parent` int(10) unsigned DEFAULT NULL,
  `left_id` int(11) NOT NULL,
  `right_id` int(11) NOT NULL,
  `page_module` smallint(5) unsigned NOT NULL,
  `page_connector` smallint(5) unsigned NOT NULL,
  `page_subject` varchar(255) NOT NULL,
  `page_title` varchar(255) DEFAULT NULL,
  `page_path` varchar(255) NOT NULL,
  `page_text` int(10) unsigned DEFAULT NULL,
  `page_children` mediumint(8) unsigned NOT NULL,
  `page_depth` smallint(5) unsigned NOT NULL DEFAULT '0',
  `page_content` tinyint(3) unsigned NOT NULL,
  `page_publish` tinyint(1) unsigned NOT NULL DEFAULT '1',
  `page_published` datetime DEFAULT NULL,
  `page_unpublished` datetime DEFAULT NULL,
  `page_time` int(10) unsigned NOT NULL,
  `page_edit_time` int(10) unsigned NOT NULL,
  `page_delete` tinyint(1) unsigned NOT NULL DEFAULT '0',
  `page_richtext` tinyint(1) unsigned NOT NULL DEFAULT '0',
  `page_cache` tinyint(1) unsigned NOT NULL DEFAULT '1',
  `page_template` varchar(255) NOT NULL,
  PRIMARY KEY (`page_id`),
  KEY `page_parent` (`page_parent`),
  KEY `left_id` (`left_id`),
  KEY `right_id` (`right_id`),
  KEY `page_depth` (`page_depth`),
  KEY `page_path` (`page_path`),
  KEY `page_connector` (`page_connector`),
  KEY `page_text` (`page_text`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;