我在获得一个非常简单的存储过程时遇到了一些困难。考虑以下文章表格片段:
id replaced_by baseID
1 2 0
2 3 0
3 0 0
一个简单的分层表,使用写时复制。编辑文章时,当前文章的 replace_by 字段设置为其新副本的 id。
我添加了一个 baseID 字段,将来应该存储文章的 baseID。在我上面的示例中,有一篇文章(例如 id 3)。它的 baseID 为 1。
为了获取 baseID,我创建了以下存储过程:
DELIMITER $$
CREATE FUNCTION getBaseID(articleID INT) RETURNS INT
BEGIN
DECLARE x INT;
DECLARE y INT;
SET x = articleID;
sloop:LOOP
SELECT id INTO y FROM article WHERE replaced_by_articleID = x;
IF y IS NOT NULL THEN
SET x = y;
ITERATE sloop;
ELSE
LEAVE sloop;
END IF;
END LOOP;
RETURN x;
END $$
DELIMITER ;
看起来很简单,直到我实际使用以下方法调用该函数:
SELECT getBaseID(3);
我希望该函数返回 1。我什至愿意理解它可能需要一秒钟。相反,机器的 CPU 上升到 100% (mysqld)。
我什至使用REPEAT .. UNTIL
和 with重写了相同的函数WHILE .. DO
,最终结果相同。
谁能解释为什么我的 CPU 在进入循环时会上升 100%?
旁注:我只是想赢得时间。我在 PHP 中创建了完全相同的函数,它运行良好,但我们的猜测是 MySQL 可以稍微快一点。我们需要筛选大约 1800 万条记录。我能节省的任何时间都是值得的。
提前感谢您的任何帮助和/或指示。
解决的SQL:
DELIMITER $$
CREATE FUNCTION getBaseID(articleID INT) RETURNS INT
BEGIN
DECLARE x INT;
DECLARE y INT;
SET x = articleID;
sloop:LOOP
SET y = NULL;
SELECT id INTO y FROM article WHERE replaced_by_articleID = x;
IF y IS NULL THEN
LEAVE sloop;
END IF;
SET x = y;
ITERATE sloop;
END LOOP;
RETURN x;
END $$
DELIMITER ;