非常に単純なストアド プロシージャを正しく作成するのに苦労しています。次の記事の表のスニペットを検討してください。
id replaced_by baseID
1 2 0
2 3 0
3 0 0
コピーオンライトを使用した単純な階層テーブル。記事が編集されると、現在の記事の replacement_by フィールドが新しいコピーの ID に設定されます。
baseID フィールドを追加しました。これは、将来、記事の baseID を格納する必要があります。上記の私の例では、1 つの記事 (例: 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
と を使用して同じ関数を書き直してもWHILE .. DO
、同じ最終結果が得られました。
ループに入ったときに CPU が 100% 上昇する理由を誰か説明できますか?
補足: 私は単純に時間を稼ごうとしています。私はまったく同じ関数を PHP で作成しましたが、これは正常に実行されますが、MySQL の方がわずかに高速であると推測されます。約 1,800 万件のレコードをふるいにかける必要があります。少しでも節約できる時間は、それだけの価値があります。
事前に支援および/またはポインタをありがとう.
解決済みの 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 ;