使用临时表的存储过程性能

vce*_*ick 2 mysql stored-procedures

我有以下存储过程我想提高性能

DELIMITER $$
CREATE PROCEDURE NEXT_UNIT_OF_WORK
(
    IN batchId INT,
    IN size INT
)
BEGIN

   start transaction;

   CREATE TEMPORARY TABLE IF NOT EXISTS BATCH_ITEMS_UOW ENGINE=MEMORY AS (SELECT ID FROM BATCH_ITEMS WHERE STATUS = 'UNPROCESSED' AND BATCH_JOB_ID = batchId LIMIT size);

   UPDATE BATCH_ITEMS SET STATUS = 'PROCESSING' WHERE BATCH_JOB_ID = batchID AND ID IN (SELECT ID FROM BATCH_ITEMS_UOW);

   SELECT * FROM BATCH_ITEMS_UOW;

   DROP TABLE BATCH_ITEMS_UOW;

   commit;
END $$
DELIMITER ;
Run Code Online (Sandbox Code Playgroud)

其目的是通过由批处理作业 ID 标识并限制为多个项目(大小)的存储过程获取一批批处理项目。

该查询最初似乎需要 1 秒,然后每次调用存储过程都会连续花费更长的时间。

鉴于此存储过程每分钟将被多个线程调用数百次,花费这么长时间是不可接受的。

有没有更好的方法来处理这个存储过程?

Mic*_*bot 6

为了回答评论中出现的问题,MySQL 中的临时表归创建它们的客户端连接(会话、线程)所有,并且仅可用于创建它们的客户端连接(会话、线程),因此不存在隔离问题,但是您的连接存在潜在问题之前在那里留下了具有该名称的东西,要么是陈旧的数据,要么是具有不同结构的类似名称的表,其中任何一个都不太理想。

CREATE TEMPORARY TABLE IF NOT EXISTS如果没有同名的表,该语句将创建临时表,但如果表已经存在,则该语句是一个非阻塞无操作,如前所述,这仍然很糟糕。更好的选择可能是在创建它之前删除位于 proc 顶部的临时表,如果它在那里,那么你总是从一个干净的环境开始。如果临时表不存在,这同样是一个空操作:

   DROP TEMPORARY TABLE IF EXISTS BATCH_ITEMS_UOW;
Run Code Online (Sandbox Code Playgroud)

重要提示:如果您在 BATCH_ITEMS 表的 STATUS 列上没有索引,这将是此过程比所需速度慢的两个主要原因之一。无论是使用此代码还是现有代码,这对于性能来说都是必不可少的。

最好为临时表建立索引,以使优化器的工作尽可能轻松。请注意,声明的列必须与 中列的名称或别名相同SELECT,否则 MySQL 假定SELECT应该使用 中的列名为临时表生成附加SELECT

   CREATE TEMPORARY TABLE BATCH_ITEMS_UOW (
     ID INT NOT NULL PRIMARY KEY
   ) ENGINE=MEMORY AS (
    SELECT ID FROM BATCH_ITEMS 
     WHERE STATUS = 'UNPROCESSED' 
       AND BATCH_JOB_ID = batchId 
     LIMIT size
   );
Run Code Online (Sandbox Code Playgroud)

然后,而不是使用子查询的更新,这应该是连接,因为这些通常在任何版本的 MySQL 中都得到了更好的优化。这是此过程可能比您预期的要慢的另一个可能原因。

UPDATE BATCH_ITEMS BI
  JOIN BATCH_ITEMS_UOW UOW ON UOW.ID = BI.ID
   SET BI.STATUS = 'PROCESSING';
Run Code Online (Sandbox Code Playgroud)

然后返回结果集...

SELECT * FROM BATCH_ITEMS_UOW;
Run Code Online (Sandbox Code Playgroud)

或者,您可以删除临时表......当您的会话断开连接时,或下次运行此过程时,它将自动删除,因为如果您在同一会话中再次运行它,我们现在会在开始时显式删除它.

DROP TEMPORARY TABLE BATCH_ITEMS_UOW;
Run Code Online (Sandbox Code Playgroud)