gpt4 book ai didi

mysql - Nodejs Mysql 优化查询

转载 作者:行者123 更新时间:2023-11-29 17:42:41 25 4
gpt4 key购买 nike

我在nodejs v8.9.4中使用mysql2模块。
这是我从消息队列中获取满足以下条件的消息的函数:

状态==0
如果 status==1botId 数量小于 10
如果 wait 表中 botId+chatIdretry_after 并且 botId 小于 NOW(时间戳)
如果没有与 status==1

相同的 chatId
  static async Find(activeMessageIds, maxActiveMsgPerBot) {

let params = [maxActiveMsgPerBot];
let filterActiveMessageIds = ' ';
let time = Util.GetTimeStamp();

if (activeMessageIds && activeMessageIds.length) {
filterActiveMessageIds = 'q.id NOT IN (?) AND ';
params.push(activeMessageIds);
}

let q =
`select q.*
from bot_message_queue q
left join bot_message_queue_wait w on q.botId=w.botId AND q.chatId=w.chatId
left join bot_message_queue_wait w2 on q.botId=w2.botId AND w2.chatId=0
where
q.status=0 AND
q.botId NOT IN (select q2.botId from bot_message_queue q2 where q2.status=1 group by q2.botId HAVING COUNT(q2.botId)>?) AND
${filterActiveMessageIds}
q.chatId NOT IN (select q3.chatId from bot_message_queue q3 where q3.status=1 group by q3.chatId) AND
(w.retry_after IS NULL OR w.retry_after <= ?) AND
(w2.retry_after IS NULL OR w2.retry_after <= ?)
order by q.priority DESC,q.id ASC
limit 1;`;

params.push(time);
params.push(time);

let con = await DB.connection();
let result = await DB.query(q, params, con);
if (result && result.length) {
result = result[0];
let updateQ = `update bot_message_queue set status=1 where id=?;`;
await DB.query(updateQ, [result.id], con);
} else
result = null;

con.release();
return result;
}

此查询在我的本地开发系统上运行良好。它在 phpmyadmin 服务器中也可以在几毫秒内正常运行。

但是当它运行时抛出nodejs+mysql2,CPU使用率上升到100%该表中只有 2K 行。

CREATE TABLE IF NOT EXISTS `bot_message_queue` (
`id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`botId` int(10) UNSIGNED NOT NULL,
`chatId` varchar(50) CHARACTER SET utf8 NOT NULL,
`type` varchar(50) DEFAULT NULL,
`message` longtext NOT NULL,
`add_date` int(10) UNSIGNED NOT NULL,
`status` tinyint(2) UNSIGNED NOT NULL DEFAULT '0' COMMENT '0=waiting,1=sendig,2=sent,3=error',
`priority` tinyint(1) UNSIGNED NOT NULL DEFAULT '5' COMMENT '5=normal messages,<5 = bulk messages',
`delay_after` int(10) UNSIGNED NOT NULL DEFAULT '1000',
`send_date` int(10) UNSIGNED DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `botId` (`botId`,`status`),
KEY `botId_2` (`botId`,`chatId`,`status`,`priority`),
KEY `chatId` (`chatId`,`status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE TABLE IF NOT EXISTS `bot_message_queue_wait` (
`botId` int(10) UNSIGNED NOT NULL,
`chatId` varchar(50) CHARACTER SET utf8 NOT NULL,
`retry_after` int(10) UNSIGNED NOT NULL,
PRIMARY KEY (`botId`,`chatId`),
KEY `retry_after` (`retry_after`),
KEY `botId` (`botId`,`chatId`,`retry_after`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

更新:Real table data here更新2:
获取消息时间:
- 最短:1788 毫秒
- 最大:44285 毫秒
- 平均:20185.4 毫秒

直到昨天为止,最大值大约是 20 毫秒:( 现在是 40 秒!!!

更新 3:我合并了这 2 个连接和位置:

left join bot_message_queue_wait w on q.botId=w.botId AND q.chatId=w.chatId 
left join bot_message_queue_wait w2 on q.botId=w2.botId AND w2.chatId=0

(w.retry_after IS NULL OR w.retry_after <= ?) AND
(w2.retry_after IS NULL OR w2.retry_after <= ?)

变成一个,我希望这能按预期工作!

left join bot_message_queue_wait w on q.botId=w.botId AND ( q.chatId=w.chatId OR w.chatId=0 )

暂时我删除了 2 个 where,查询时间恢复正常。

q.botId NOT IN (select ...)
q.chatId NOT IN (select ...)

因此,这两个查询是阻塞点,需要修复。

最佳答案

NOT IN ( SELECT ... ) 很难优化。

OR 无法优化。

ORDER BY中,混合DESCASC消除了索引的使用(直到8.0)。考虑将 ASC 更改为 DESC。之后,INDEX(priority, id)可能有所帮助。

什么是${filterActiveMessageIds}

不需要GROUP BY

 NOT IN ( SELECT  q3.chatId
from bot_message_queue q3
where q3.status=1
group by q3.chatId )

INDEX(status, chatid) 按此顺序将使该子查询受益。

INDEX(status, botid) 按此顺序

有关索引创建的更多信息:http://mysql.rjweb.org/doc.php/index_cookbook_mysql

关于mysql - Nodejs Mysql 优化查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49937703/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com