根据您的要求,以下是关注代码中性能问题的评论:
优化 add_item()
假设products_available_tbl
有一个唯一索引item_id
,那么
CREATE PROCEDURE add_item(IN in_producer_id INT, IN in_item_id INT,
IN in_item_cnt INT)
BEGIN
DECLARE item INT DEFAULT NULL;
START TRANSACTION;
INSERT INTO producer_tbl (producer_id, item_id, item_cnt)
VALUES (in_producer_id, in_item_id, in_item_cnt);
SELECT item_id FROM products_available_tbl
WHERE item_id=in_item_id INTO item FOR UPDATE;
IF item IS NOT NULL THEN
UPDATE products_available_tbl
SET avail_cnt=avail_cnt + in_item_cnt
WHERE item_id=in_item_id;
ELSE
INSERT INTO products_available_tbl
(item_id, avail_cnt, blocked_cnt)
VALUES (in_item_id, in_item_cnt, 0);
END IF;
COMMIT;
END //
可以改写为:
CREATE PROCEDURE add_item(IN in_producer_id INT, IN in_item_id INT,
IN in_item_cnt INT)
BEGIN
START TRANSACTION;
INSERT INTO producer_tbl (producer_id, item_id, item_cnt)
VALUES (in_producer_id, in_item_id, in_item_cnt);
INSERT INTO products_available_tbl SET
item_id = in_item_id,
avail_cnt = in_item_cnt,
blocked_cnt = 0
ON DUPLICATE KEY UPDATE
avail_cnt = avail_cnt + in_item_cnt;
COMMIT;
END //
优化 block_item()
优化很重要,所以让我们分阶段进行:
首先,让我们重写
SET out_cnt = var_avail_cnt - var_blocked_cnt;
IF out_cnt >= cnt THEN
SET out_cnt = cnt;
END IF;
作为
SET out_cnt = LEAST(var_avail_cnt - var_blocked_cnt, cnt);
接下来我们重写
SELECT avail_cnt, blocked_cnt FROM products_available_tbl
WHERE item_id=in_item_id INTO var_avail_cnt, var_blocked_cnt
FOR UPDATE;
SET out_cnt = LEAST(var_avail_cnt - var_blocked_cnt, cnt);
作为
SELECT LEAST(avail_cnt - blocked_cnt, cnt) FROM products_available_tbl
WHERE item_id=in_item_id INTO out_cnt
FOR UPDATE;
最后,让我们重写
SELECT LEAST(avail_cnt - blocked_cnt, cnt) FROM products_available_tbl
WHERE item_id=in_item_id INTO out_cnt
FOR UPDATE;
UPDATE products_available_tbl
SET blocked_cnt = var_blocked_cnt + out_cnt
WHERE item_id = in_item_id;
作为
UPDATE products_available_tbl
SET
blocked_cnt = blocked_cnt + (@out_cnt := LEAST(avail_cnt - blocked_cnt, cnt))
WHERE item_id = in_item_id;
所以
CREATE PROCEDURE block_item(IN in_item_id INT, INOUT cnt INT)
BEGIN
DECLARE out_cnt INT DEFAULT cnt;
DECLARE var_avail_cnt, var_blocked_cnt INT DEFAULT 0;
START TRANSACTION;
SELECT avail_cnt, blocked_cnt FROM products_available_tbl
WHERE item_id=in_item_id INTO var_avail_cnt, var_blocked_cnt
FOR UPDATE;
SET out_cnt = var_avail_cnt - var_blocked_cnt;
IF out_cnt >= cnt THEN
SET out_cnt = cnt;
END IF;
UPDATE products_available_tbl
SET blocked_cnt = var_blocked_cnt + out_cnt
WHERE item_id = in_item_id;
SET cnt = out_cnt;
COMMIT;
END //
变成
CREATE PROCEDURE block_item(IN in_item_id INT, INOUT cnt INT)
BEGIN
UPDATE products_available_tbl
SET
blocked_cnt = blocked_cnt + (@out_cnt := LEAST(avail_cnt - blocked_cnt, cnt))
WHERE item_id = in_item_id;
SET cnt = @out_cnt;
END //
优化 commit_item():
让我们重写
CREATE PROCEDURE commit_item(IN in_item_id INT, INOUT cnt INT)
BEGIN
DECLARE out_cnt INT DEFAULT cnt;
DECLARE var_avail_cnt, var_blocked_cnt INT DEFAULT 0;
START TRANSACTION;
SELECT avail_cnt, blocked_cnt FROM products_available_tbl
WHERE item_id=in_item_id INTO var_avail_cnt, var_blocked_cnt
FOR UPDATE;
IF cnt > var_blocked_cnt THEN
SET out_cnt = -1; /* Error case: Caller supplied wrong value. */
ELSEIF var_blocked_cnt > var_avail_cnt THEN
SET out_cnt = -2; /* Error case: Bug in block_item proc. */
ELSE
SET out_cnt = cnt;
UPDATE products_available_tbl
SET blocked_cnt = var_blocked_cnt - out_cnt,
avail_cnt = var_avail_cnt - out_cnt
WHERE item_id = in_item_id;
END IF;
SET cnt = out_cnt;
COMMIT;
END //
作为
CREATE PROCEDURE commit_item(IN in_item_id INT, INOUT cnt INT)
proc: BEGIN
DECLARE var_avail_cnt, var_blocked_cnt INT DEFAULT 0;
UPDATE products_available_tbl
SET blocked_cnt = blocked_cnt - cnt,
avail_cnt = avail_cnt - cnt
WHERE item_id = in_item_id
AND cnt <= blocked_cnt
AND blocked_cnt <= avail_cnt;
IF ROW_COUNT() > 0 THEN
LEAVE proc;
END IF;
SELECT avail_cnt, blocked_cnt FROM products_available_tbl
WHERE item_id=in_item_id INTO var_avail_cnt, var_blocked_cnt;
IF cnt > var_blocked_cnt THEN
SET cnt = -1; /* Error case: Caller supplied wrong value. */
ELSEIF var_blocked_cnt > var_avail_cnt THEN
SET cnt = -2; /* Error case: Bug in block_item proc. */
ELSE
SET cnt = -3; /* UPDATE failed, reasons unknown. */
END IF;
END //
我希望这些帮助。让我知道你的想法!