リクエストごとに、以下はコードのパフォーマンスの問題に焦点を当てたコメントです。
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 //
これらの助けを願っています。どう考えているか教えてください!