我有一个大文件,每行都有JSON记录。 我正在编写一个脚本,以通过API将这些记录的子集上载到CouchDB,并尝试各种方法来查看最快的方法。 这是我发现工作最快或最慢的方法(在本地主机上的CouchDB实例上):
将每个所需的记录读入内存。 将所有记录存储在内存中后,为每个记录生成一个上传协程,并立即收集/运行所有协程
同步读取文件,并在遇到所需记录时同步上传
使用aiofiles读取文件,并在遇到所需记录时异步更新
方法1比其他两种方法快得多(大约快一倍)。 我很困惑为什么方法2比方法3更快,尤其是与此处的示例相反, 该示例异步运行所需的时间比同步运行所需的时间少一半(未提供同步代码,必须自己重写)。 是上下文从文件I / O切换到HTTP I / O,尤其是与API上传相比,文件读取的发生频率要高得多吗?
为了进一步说明,这是代表每种方法的一些Python伪代码:
方法1-同步文件IO,异步HTTP IO
import json
import asyncio
import aiohttp
records = []
with open('records.txt', 'r') as record_file:
for line in record_file:
record = json.loads(line)
if valid(record):
records.append(record)
async def batch_upload(records):
async with aiohttp.ClientSession() as session:
tasks = []
for record in records:
task = async_upload(record, session)
tasks.append(task)
await asyncio.gather(*tasks)
asyncio.run(batch_upload(properties))
方法2-同步文件IO,同步HTTP IO
import json
with open('records.txt', 'r') as record_file:
for line in record_file:
record = json.loads(line)
if valid(record):
sync_upload(record)
方法3-异步文件IO,异步HTTP IO
import json
import asyncio
import aiohttp
import aiofiles
async def batch_upload()
async with aiohttp.ClientSession() as session:
async with open('records.txt', 'r') as record_file:
line = await record_file.readline()
while line:
record = json.loads(line)
if valid(record):
await async_upload(record, session)
line = await record_file.readline()
asyncio.run(batch_upload())
我正在使用的文件大小约为1.3 GB,共有100000条记录,我上传了691条。 每次上传均以GET请求开头,以查看记录是否已存在于CouchDB中。 如果是这样,则执行PUT以使用任何新信息来更新CouchDB记录; 如果不是,则将记录过帐到数据库。 因此,每个上传都包含两个API请求。 出于开发目的,我仅创建记录,因此我运行GET和POST请求,总共1382个API调用。
方法1大约需要17秒,方法2大约需要33秒,方法3大约需要42秒。