感觉 aiomysql,异步执行多个查询,性能并没有显著的提升啊

2021-07-21 16:12:06 +08:00
 ErenJaeger

代码如下:

 async def query(self, query, param=None):
        conn, cur = await self.getCursor()
        try:
            await cur.execute(query, param)
            return await cur.fetchall()
        except:
            print('error')
        finally:
            if cur:
                await cur.close()
            await self.pool.release(conn)

# mysqlobj 是 aiomysql 连接池对象

result = await asyncio.gather(mysqlobj.query(sql1), mysqlobj.query(sql2), mysqlobj.query(sql3), mysqlobj.query(sql4), mysqlobj.query(sql5))

在我的理解中,如果异步执行的话,这段代码执行的时长应该是这 5 个 sql 中耗时最长的时长,但是测试多次,相对同步执行这 5 个 sql 来说,执行时间并没有显著的提升。各位大佬能指点一下吗?

3916 次点击
所在节点    Python
40 条回复
ErenJaeger
2021-07-21 18:12:08 +08:00
@chaleaoch 淦,我调了 1000 次,同步 40 多秒,异步 5 秒多。问题生产环境中一个接口里面不可能会有这么高频次的查询,小频次的查询,同步异步的差距就很不明显
BBCCBB
2021-07-21 18:12:54 +08:00
次数调大点试试. 看起来没啥问题. 可以把代码贴完整点, 包括 loop.run_until_complete()这一块
BBCCBB
2021-07-21 18:14:57 +08:00
一个接口不可能这么高, 但是其他的接口也有网络 io, 和你测一个接口 1000 次概念差不多, 并发上去了, asyncio 性能差异就出来了..

如果只是一个接口, 没啥访问, 直接同步搞.. 简单
ErenJaeger
2021-07-21 18:14:59 +08:00
@BBCCBB gather 里面是顺序执行的吗?我看官方文档里是这样描述的:
同时运行 aws 序列中的可等待对象。

如果 aws 中的任何 awaitable 是协程,则它会自动安排为任务。

如果所有 awaitable 都成功完成,则结果是返回值的聚合列表。结果值的顺序对应于 aws 中等待的顺序。

如果 return_exceptions 为 False (默认),第一个引发的异常会立即传播到在 gather() 上等待的任务。aws 序列中的其他等待对象不会被取消,而是会继续运行。

如果 return_exceptions 为 True,则将异常视为成功结果,并在结果列表中聚合。

如果 gather() 被取消,所有提交的等待(尚未完成)也将被取消。

如果 aws 序列中的任何 Task 或 Future 被取消,则将其视为引发了 CancelledError - 在这种情况下不会取消 gather() 调用。这是为了防止取消一个提交的任务 /未来导致其他任务 /未来被取消。
ErenJaeger
2021-07-21 18:20:55 +08:00
class Pmysql:

def __init__(self):
self.conn = None
self.pool = None

async def initpool(self):
try:
__pool = await aiomysql.create_pool(minsize=10,
maxsize=10,
host=Config.host,
port=Config.port,
user=Config.user,
password=Config.password,
db='db')
return __pool
except Exception as e:
print(e)
print('create connect error.')

async def getCursor(self):
conn = await self.pool.acquire()
cur = await conn.cursor()
return conn, cur

async def query(self, query, param=None):
conn, cur = await self.getCursor()
try:
await cur.execute(query, param)
return await cur.fetchall()
except:
print('error')
finally:
if cur:
await cur.close()
await self.pool.release(conn)

async def getAmysqlobj():
mysqlobj = Pmysql()
pool = await mysqlobj.initpool()
mysqlobj.pool = pool
return mysqlobj
BBCCBB
2021-07-21 18:28:32 +08:00
gather 不是顺序执行, 都 asyncio 了, 只要里面 task 不阻塞, 就是异步执行的.

你这个没啥问题, 根据你加大到 1000 次, 差距挺大的, 所以应该是量不够大.
ErenJaeger
2021-07-21 18:34:30 +08:00
@BBCCBB 其实最大的需求,还是提升响应效率了,这个查询 2s 多能降到 1s 多,甚至不到 1s,就是最高的期望值了,但是测试感觉难以实现
BBCCBB
2021-07-21 18:44:57 +08:00
asyncio 不能降低你代码里单个 query 方法的耗时, 他要做的是用少量线程就能支撑超高的并发量,, 这个用线程是很难实现的, 单个请求的响应时间并不会变得更快,
vindurriel
2021-07-21 19:45:01 +08:00
sql 是啥 可以换成 sleep(1) 看是 n 秒返回还是 1 秒多返回
myCupOfTea
2021-07-22 08:45:58 +08:00
楼主写法没问题,怎么好多人说不是并发 gather 不就是并发吗
myCupOfTea
2021-07-22 08:47:39 +08:00
但是这类数据库的库,其实异步并发不会比多线程好
因为这类库很多都是底层用的 run_in_excutor,其实就是跑线程池(还是要看具体代码,至少 mongodb 官方的异步库是这样的)
ErenJaeger
2021-07-22 08:50:57 +08:00
@BBCCBB 是呀,我本来是想着,并发执行多个 sql,这样将整体查询时长降低至最长查询的那个 sql 。但是感觉并没有达到预期的效果
RockShake
2021-07-22 09:11:24 +08:00
异步并不是多线程啊,异步是模拟 Javascript 的逻辑,将程序操作简化为一个线程,使用这个逻辑可以实现 await 功能,详见: https://ruanyifeng.com/blog/2019/11/python-asyncio.html
xxfye
2021-07-22 09:21:18 +08:00
@ErenJaeger 你对异步的理解错了,异步是让一个餐馆合理分配上菜时间使其能够装下更多的顾客,而不是让每个顾客等待上菜的时间减少。
www5070504
2021-07-22 09:45:57 +08:00
等待时间应该是最长的那个吧 比原来顺序执行肯定短了不少 但是也不可能减少最长的那个请求的时间
forbxy
2021-07-22 11:18:37 +08:00
python 的协程,包括这个库只是为了单线程服务器在处理 mysql 不会卡住,可以切到其他用户的连接处理
niu0619
2021-07-22 14:05:42 +08:00
ErenJaeger
2021-07-22 14:09:35 +08:00
@xxfye 如果流程是点菜、做菜、上菜的话。同步应该是来一个人点菜、做菜、上菜,下一个人,点菜、做菜、上菜。。。。这样
异步的话,就是同时面对多个人,如果 1 个人在点菜,不会卡在等待他点菜这个地方,而是去做其他已经点好菜的客户的菜,等到点好菜,在做菜,不知道我这个描述对不对,反正厨师觉得 mmp
ErenJaeger
2021-07-22 14:11:56 +08:00
@RockShake 确实不是多线程,只是我想在执行多个查询的时候,某个查询网络 IO 的时候,可以发起其他查询。减少访问时间
ElmerZhang
2021-07-22 16:06:37 +08:00
@ErenJaeger #21
相当于某个 API 的耗时从 40ms 优化到 5ms,在某些高性能场景下,这是非常大的提升了

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/790872

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX