s3 - 如何获得文件的快速行数? wc -l 太慢了

s3 - how to get fast line count of file? wc -l is too slow

有没有人可以快速获取 S3 中托管文件的行数?最好使用 CLI、s3api,但我也对 python/boto 持开放态度。 注意:解决方案必须 运行 非交互式,即在隔夜批处理中。

不对,我正在这样做,它可以工作,但处理一个 20GB 的文件大约需要 10 分钟:

 aws cp s3://foo/bar - | wc -l

以下两种方法可能对您有用...

Amazon S3 有一项名为 S3 Select 的新功能,可让您查询存储在 S3 上的文件。

您可以对文件中的记录(行)数进行计数,它甚至可以用于 GZIP 文件。结果可能因文件格式而异。

Amazon Athena 也是一个可能合适的类似选项。它可以查询存储在 Amazon S3 中的文件。

是的,Amazon S3 具有 SELECT 功能,在从 SELECT 选项卡执行任何查询时还要注意成本。. 例如,这是@Jun2018 的价格(这可能会有所不同) S3 Select 定价基于输入、输出和传输的数据的大小。 每个查询的费用为每扫描 GB 0.002 美元,再加上返回的每 GB 0.0007 美元。

您可以使用 python/boto3 来完成。 定义 bucket_name 和前缀:

colsep = ','
s3          = boto3.client('s3')
bucket_name = 'my-data-test'
s3_key = 'in/file.parquet'

请注意,S3 SELECT 一次只能访问一个文件。

现在您可以打开 S3 SELECT 游标:

sql_stmt    = """SELECT count(*) FROM s3object S"""  
req_fact =s3.select_object_content(
    Bucket  = bucket_name,
    Key     = s3_key,
    ExpressionType  = 'SQL',
    Expression      = sql_stmt,
    InputSerialization={'Parquet': {}},
    OutputSerialization = {'CSV': {
                'RecordDelimiter': os.linesep,
                'FieldDelimiter': colsep}},
    
)

现在遍历返回的记录:

for event in req_fact['Payload']:
    if 'Records' in event:
        rr=event['Records']['Payload'].decode('utf-8')
        for i, rec in enumerate(rr.split(linesep)):
            if rec:
                row=rec.split(colsep)
                if row:
                    print('File line count:', row[0])

如果您想计算给定 S3 目录中所有镶木地板文件中的记录,请查看此 python/boto3 脚本:S3-parquet-files-row-counter