Glue – Athena Custom Output File Size And Fixed Number Of Files
CÂU HỎI: Làm sao để có thể chỉ định size của file được chia hoặc số file được chia ra? (Dịch vụ: Athena/Glue)
Tham khảo: https://thedataguy.in/aws-glue-custom-output-file-size-and-fixed-number-of-files/
Dữ liệu mẫu: Cần có khoảng ~10 file csv -> sẽ transform về còn 2 file thôi!
Query với Athena:
Tạo bảng:
CREATE EXTERNAL TABLE IF NOT EXISTS aaaa (
dispatching_base_num string,
pickup_date string,
locationid bigint)
STORED AS PARQUET
LOCATION 's3://athena-examples/parquet/'
tblproperties ("parquet.compress"="SNAPPY");
2. Insert thử:
insert into aaaa ("dispatching_base_num", "pickup_date", "locationid") values ('aa', 'vvv', 123);
Lưu ý:
values phải là single quote, nếu double quote kiểu:
insert into aaaa ("dispatching_base_num", "pickup_date", "locationid") values ("aa", "vvv", 123);
sẽ gặp lỗi:
SYNTAX_ERROR: line 1:80: Column 'aa' cannot be resolved. If a data manifest file was generated at 's3://csv-parge/parquet/athena/Unsaved/2022/04/11/f6b9b28c-014b-4a7e-af4e-9be6d1c7c114-manifest.csv', you may need to manually clean the data from locations specified in the manifest. Athena will not delete data in your account.
This query ran against the "default" database, unless qualified by the query. Please post the error message on our forum
or contact customer support
with Query Id: f6b9b28c-014b-4a7e-af4e-9be6d1c7c114
Tham khảo thêm về repartition tại đây:
https://docs.aws.amazon.com/glue/latest/dg/aws-glue-programming-python-samples-legislators.html
Trích dẫn quan trọng:
To put all the history data into a single file, you must convert it to a data frame, repartition it, and write it out:
s_history = l_history.toDF().repartition(1)
s_history.write.parquet('s3://glue-sample-target/output-dir/legislator_single')
Nếu chỉ để giải quyết vấn đề file nhỏ, không nhất định chỉ định file thì có thể làm theo đây:
https://aws.amazon.com/vi/premiumsupport/knowledge-center/glue-job-output-large-files/
Ngoài ra còn có thể:
You are right that INSERT INTO is not yet supported for bucketed tables. For your use case where you wanted to specify the number of buckets/file sizes, using Athena bucketing would be appropriate but, with the downfall of not being able to use INSERT INTO to insert new incoming data.
But, I can recommend of using S3distcp utility on AWS EMR to merge small files into ~128MB size to solve your small file problem. You can use it to combine smaller files into larger objects. You can also use S3DistCP to move large amounts of data in an optimized fashion from HDFS to Amazon S3, Amazon S3 to Amazon S3, and Amazon S3 to HDFS.
REFERENCES:
https://docs.aws.amazon.com/emr/latest/ReleaseGuide/UsingEMR_s3distcp.html
Câu hỏi 1:
Khi chỉ sử dụng mỗi câu lệnh partition clause, thì data sẽ được chia thành 30 files, mỗi file có dung lượng <1MB. Vì file có dung lượng nhỏ, nên có thể ảnh hưởng đến tốc độ truy vấn. => Làm sao để có thể chỉ định size của file được chia hoặc số file được chia ra?
Solution 1:
Để chỉ định file size hay số lượng output file, có thể sử dụng kỹ thuật “Bucketing” với Athena. Cách thực hiện được hướng dẫn trong bài viết sau:
How can I set the number or size of files when I run a CTAS query in Athena?
Tuy nhiên, với kỹ thuật này thì có một lưu ý: Bucketed table không hỗ trợ INSERT INTO.
Câu hỏi 2:
Cùng context như trên, nhưng lại muốn sử dụng câu lệnh INSERT INTO thì làm thế nào?
Solution 2:
Sử dụng Glue repartition:
Các bước thực hiện tham khảo bài viết sau:
[Build a Data Lake Foundation with AWS Glue and Amazon S3]https://aws.amazon.com/blogs/big-data/build-a-data-lake-foundation-with-aws-glue-and-amazon-s3/
Lưu ý rằng, tại bước “13.View the job.” trong bài viết, cần add thêm đoạn code:
datasource_df = dropnullfields3.repartition(<số file output bạn mong muốn>)
vào sau dòng
dropnullfields3 = DropNullFields.apply(frame = resolvechoice2, transformation_ctx = "dropnullfields3")
và sửa lại
datasink4 = glueContext.write_dynamic_frame.from_options(frame = dropnullfields3, connection_type = "s3", connection_options = {"path": "<your_s3_path>"}, format = "parquet", transformation_ctx = "datasink4")
thành
datasink4 = glueContext.write_dynamic_frame.from_options(frame = datasource_df, connection_type = "s3", connection_options = {"path": "<your_s3_path>"}, format = "parquet", transformation_ctx = "datasink4")
Tham khảo thêm về repartition tại đây:
https://docs.aws.amazon.com/glue/latest/dg/aws-glue-programming-python-samples-legislators.html
Query với Athena:
Tạo bảng:
CREATE EXTERNAL TABLE IF NOT EXISTS aaaa (
dispatching_base_num string,
pickup_date string,
locationid bigint)
STORED AS PARQUET
LOCATION 's3://athena-examples/parquet/'
tblproperties ("parquet.compress"="SNAPPY");
Insert thử:
insert into aaaa ("dispatching_base_num", "pickup_date", "locationid") values ('aa', 'vvv', 123);
Câu query insert thành công → done!
Comment:
Cái này chỉ chỉ định được số file mong muốn thôi, nếu size tổng tăng lên thì size từng file tăng lên. Tuy nhiên bài toán mong muốn ban đầu là chỉ định được số file, hoặc file size. File size thì sẽ khó có thể chỉ định rõ ràng đc, nên tạm thời giải quyết chỉ định số file tạo ra.
file size thì chính AWS cũng trả lời em như sau: “Due to how big data is handled by a distributed process it is not possible to set the final file size before processing begins, AWS Glue jobs will also encounter a similar issue. However, when using AWS Glue you have more control over the process and this may allow you to implement some additional logic to allow you to complete this use case.”
Từ AWS:
Excuse me, but as you have confirmed, bucketing is the only way to control the number of files output by Athena.
For this reason, we would like you to consider adjusting to output a larger file with a Glue job etc. instead of the INSERT INTO query, or combining the files output by the INSERT INTO query separately.
We apologize for the inconvenience, but we would appreciate it if you could consider how to respond according to your requirements.
--INSERT INTO --Amazon Athena
https://docs.aws.amazon.com/ja_jp/athena/latest/ug/insert-into.html
==
important
Inserting rows using VALUES is not recommended because Athena generates a file for each INSERT operation. This creates a large number of small files and can slow down table query performance.