我们这边有一个接口,里面会做很多的查询操作,会查各种表,单个表的查询其实并不慢,但是一旦查询的次数多了,加起来就会慢。 例如查询一个用户的信息,会连带着查相关的信息,这些信息保存在其他表里,那么现在想并发的查询这些账号的信息。 然后查好后再合并到一起。
await Promise.All([查询1,查询2]) 试试?
可试试:
@dbit-xia 我试了下,类似于下面这样,查询语句是按照,4、12、13、15的顺序运行的。
await Promise.all([4,12,13,15].map(async(userId) => { await services.user.findUser(userId); }))
@waitingsong 关于第2点,我现在在尝试用 Worker threads 并发查询
@pwstrick 为啥要在 worker 作并发呢。 Promise.all 也行的,查询压力在数据库和网络io,当前进程又不会有啥压力。
@waitingsong 因为我试下来,数据库语句还是按顺序在查,我想要的效果同时查数据库
@pwstrick 试试不要await,而是直接返回promise await Promise.all([4,12,13,15].map((userId) => { services.user.findUser(userId); }))
@zhennann 这样
await Promise.all([4,12,13,15].map((userId) => { return services.user.findUser(userId); }))
await 被滥用的地方之一, https://zhuanlan.zhihu.com/p/75946868)
const waitTime = async (time) => { return new Promise((res) => { setTimeout(() => res(time), time) }); } (async ()=>{ console.time('串行') await waitTime(2000) await waitTime(1000) console.timeEnd('串行') console.time('并行') await Promise.all([waitTime(2000), waitTime(1000)]) console.timeEnd('并行') })()
@waitingsong 对
@zhennann @waitingsong 我尝试了下两种写法,第一种是你们说的,省略了async
const start1 = Date.now(); const userList1 = await Promise.all( [4, 12, 13, 15, 18, 21, 22, 23, 24, 26].map((userId) => { console.log(Date.now(), userId); return services.user.findUser(userId); }) ); const end1 = Date.now();
从打印的结果中,可以看到并发。
1663831219351 4 1663831219351 12 1663831219351 13 1663831219352 15 1663831219352 18 1663831219352 21 1663831219352 22 1663831219353 23 1663831219353 24 1663831219354 26
然后我又将async加上。
const start2 = Date.now(); const userList2 = await Promise.all([27, 28, 29, 30, 31, 32, 33, 34, 35, 36].map(async (userId) => { console.log(Date.now(), userId); return services.user.findUser(userId); }) ); const end2 = Date.now();
从打印的结果中,也可以看到并发。
1663831219575 27 1663831219575 28 1663831219575 29 1663831219576 30 1663831219576 31 1663831219576 32 1663831219577 33 1663831219577 34 1663831219577 35 1663831219578 36
在代码最后,我还打印出了两者的执行时间
console.log('第一种', end1 - start1, userList1.length); console.log('第二种', end2 - start2, userList2.length);
发现前者没有后者高效。
第一种 224 10 第二种 59 10
之前也尝试了Worker threads,发现这玩意儿传递的对象中,其属性值不能是函数,一但有函数,就会报错。
@pwstrick 函数体中没有await语法,函数名前面加不加async都一样。两者时间不一样,跟你执行的先后有关系。多加几个循环,反复执行,再比较二者的时间效率
@pwstrick 你那个第二种,很有可能是数据库已经缓存了第一次的查询结果了。所以数量级差距这么大
看你用的什么数据库。如果是mongodb这种内存型数据库,并发查询相对于一个一个查询是肯定会快很多。 mysql 这种即使并发可能效果并不是很好,mysql这种io开销比较高。 建议使用:
Promise.allSettled([search1, search2,...])
Promise.all的缺点是其中一个reject掉,整个都会reject掉。 另外,如果查询个数 比较大了,建议控制并发数。
const mockTask = async (num) => { return new Promise((resolve) => { setTimeout(() => { resolve(num) }, 3000) }) } const searchList = [...new Array(100).keys()] const limit = 10 // 任务并发数 let list; async function main() { while ((list = searchList.splice(0, limit)) && list.length) { const result = await Promise.allSettled(list.map(n => mockTask(n))) console.log(result.map(item => item.value).toString()) } }
@zhennann @cd-xulei 我对两段代码调换了顺序,放在前面会比较慢,不过当我连续执行时,两者的时间类似,看来和执行顺序是有点关系的。 我会用到两种数据库 MongoDB 和MySQL,大部分是 MySQL 的业务。 我还想到了一种优化手段,就是之前一条一条的查询:
select * from user where id = 4; select * from user where id = 12; select * from user where id = 13; select * from user where id = 14;
改成批量查询:
select * from user where id in (4,12,13,14);
拿到结果后,在脚本代码中整合。
CNode 社区为国内最专业的 Node.js 开源技术社区,致力于 Node.js 的技术研究。
await Promise.All([查询1,查询2]) 试试?
可试试:
@dbit-xia 我试了下,类似于下面这样,查询语句是按照,4、12、13、15的顺序运行的。
@waitingsong 关于第2点,我现在在尝试用 Worker threads 并发查询
@pwstrick 为啥要在 worker 作并发呢。 Promise.all 也行的,查询压力在数据库和网络io,当前进程又不会有啥压力。
@waitingsong 因为我试下来,数据库语句还是按顺序在查,我想要的效果同时查数据库
@pwstrick 试试不要await,而是直接返回promise await Promise.all([4,12,13,15].map((userId) => { services.user.findUser(userId); }))
@zhennann 这样
await 被滥用的地方之一, https://zhuanlan.zhihu.com/p/75946868)
@waitingsong 对
@zhennann @waitingsong 我尝试了下两种写法,第一种是你们说的,省略了async
从打印的结果中,可以看到并发。
然后我又将async加上。
从打印的结果中,也可以看到并发。
在代码最后,我还打印出了两者的执行时间
发现前者没有后者高效。
之前也尝试了Worker threads,发现这玩意儿传递的对象中,其属性值不能是函数,一但有函数,就会报错。
@pwstrick 函数体中没有await语法,函数名前面加不加async都一样。两者时间不一样,跟你执行的先后有关系。多加几个循环,反复执行,再比较二者的时间效率
@pwstrick 你那个第二种,很有可能是数据库已经缓存了第一次的查询结果了。所以数量级差距这么大
看你用的什么数据库。如果是mongodb这种内存型数据库,并发查询相对于一个一个查询是肯定会快很多。 mysql 这种即使并发可能效果并不是很好,mysql这种io开销比较高。 建议使用:
Promise.all的缺点是其中一个reject掉,整个都会reject掉。 另外,如果查询个数 比较大了,建议控制并发数。
@zhennann @cd-xulei 我对两段代码调换了顺序,放在前面会比较慢,不过当我连续执行时,两者的时间类似,看来和执行顺序是有点关系的。 我会用到两种数据库 MongoDB 和MySQL,大部分是 MySQL 的业务。 我还想到了一种优化手段,就是之前一条一条的查询:
改成批量查询:
拿到结果后,在脚本代码中整合。