〜100Kページ(200〜300人の同時ユーザー)を含むWebサイトがあります。各ページは、MySQLのInnoDBテーブルで彼自身の記録を持っている - ページ:あなたは私がなどなど、ページの階層を表示するには、ネストされたセットモデルを使用して見ることができるようにネストセットモデルの最適化
page_id
page_parent
left_id
right_id
page_subject
page_children
page_depth
....
...すべてがINSERTのパフォーマンスを除いて罰金のようです、UPDATEおよびDELETEステートメント。ページを1つの親から別のものに移動するのが非常に遅く、時には〜30秒かかることがあります(!!)
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
この手順を最適化するにはどうすればよいですか?または疑問があります:ネストされたセットモデルを使用する代わりに何がありますか?
機能GET_PAGE_DEPTH():
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
ハードウェア:クアッドコアQ6600(4X 2.40+ギガヘルツ)、4ギガバイトのRAM何かアドバイスのため
ありがとう!
EDITED:
表ページは次のようになります。最初のステップとして
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;
テーブルの構造を投稿すると、特にインデックスが役立ちます。 – Jaydee
ああ、ネストされたセットの喜び - おそらく物事は良い古い隣接リストでもっとシンプルだろうか? –
テーブルの全構造を追加しました。おそらく、ページをあるノードから別のノードに移動する別の方法がありますか? – Bald