从命令行检查Parquet

122

我该如何在命令行中检查Parquet文件的内容?

目前我所看到的唯一选项是:

$ hadoop fs -get my-path local-file
$ parquet-tools head local-file | less

我希望避免创建local-file并且以JSON格式查看文件内容,而不是parquet-tools打印的无类型文本。有简单的方法吗?

13个回答

128

您可以使用parquet-tools命令中的cat--json选项,以便在没有本地副本且以JSON格式查看文件。

以下是一个示例:

parquet-tools cat --json hdfs://localhost/tmp/save/part-r-00000-6a3ccfae-5eb9-4a88-8ce8-b11b2644d5de.gz.parquet

这将以 JSON 格式输出数据:

{"name":"gil","age":48,"city":"london"}
{"name":"jane","age":30,"city":"new york"}
{"name":"jordan","age":18,"city":"toronto"}

免责声明:此测试在Cloudera CDH 5.12.0中进行。


2
谢谢!那真的很有帮助 :) 在我们的情况下,cat --json 没有起作用,但最终我们使用了parquet-tools csv input.gz.parquet | csvq -f json "select id, description" - GC268DM
1
这对我有用,但是...你能告诉我如何只显示3行吗? - puifais
6
现在是使用parquet-cli吗?首先运行brew install parquet-cli,然后执行命令parquet。https://github.com/apache/parquet-mr/tree/master/parquet-cli - Josh Hibschman
我使用 brew install parquet-tools 进行安装。您可以选择使用“head”模式仅显示几行。parquet-tools head --json [file] 将打印前5条记录。 我无法让 --records 标志工作,该标志应允许您指定要显示3条记录。 - Matt Farrow
我所使用的parquet-tools命令只有"show"、"csv"和"inspect"这几个命令,没有"cat"命令。 - undefined

88

在您的Mac上安装Homebrew(请参见https://brew.sh/),然后执行以下操作:

brew install parquet-tools

完成后,您可以在终端中使用parquet-tools二进制文件(它现在应该在您的路径中)进行各种命令。

parquet-toolsparquet-tools -h 将提供使用信息。

示例:

> parquet-tools rowcount part-00000-fc34f237-c985-4ebc-822b-87fa446f6f70.c000.snappy.parquet 
Total RowCount: 148192
> parquet-tools head -n 1 part-00000-fc34f237-c985-4ebc-822b-87fa446f6f70.c000.snappy.parquet 
:created_at = 2019-02-28T00:16:06.329Z
:id = row-wive~i58u-qaeu
:updated_at = 2019-02-28T00:16:06.329Z
agency = 1
body_style = PA
color = GY
fine_amount = 63
issue_date = 17932
issue_time = 1950
latitude = 64379050
location = 12743 DAVENTRY
longitude = 19261609
make = HYDA
marked_time = 
meter_id = 
plate_expiry_date = 18048
route = 16X2
rp_state_plate = CA
ticket_number = 1020798376
vin = 
violation_code = 22502A#
violation_description = 18 IN. CURB/2 WAY
> parquet-tools meta part-00000-fc34f237-c985-4ebc-822b-87fa446f6f70.c000.snappy.parquet 
file:                  file:/Users/matthewropp/team_demo/los-angeles-parking-citations/raw_citations/issue_month=201902/part-00000-fc34f237-c985-4ebc-822b-87fa446f6f70.c000.snappy.parquet 
creator:               parquet-mr version 1.10.0 (build 031a6654009e3b82020012a18434c582bd74c73a) 
extra:                 org.apache.spark.sql.parquet.row.metadata = {"type":"struct","fields":[{"name":":created_at","type":"string","nullable":true,"metadata":{}},{"name":":id","type":"string","nullable":true,"metadata":{}},{"name":":updated_at","type":"string","nullable":true,"metadata":{}},{"name":"agency","type":"integer","nullable":true,"metadata":{}},{"name":"body_style","type":"string","nullable":true,"metadata":{}},{"name":"color","type":"string","nullable":true,"metadata":{}},{"name":"fine_amount","type":"integer","nullable":true,"metadata":{}},{"name":"issue_date","type":"date","nullable":true,"metadata":{}},{"name":"issue_time","type":"integer","nullable":true,"metadata":{}},{"name":"latitude","type":"decimal(8,1)","nullable":true,"metadata":{}},{"name":"location","type":"string","nullable":true,"metadata":{}},{"name":"longitude","type":"decimal(8,1)","nullable":true,"metadata":{}},{"name":"make","type":"string","nullable":true,"metadata":{}},{"name":"marked_time","type":"string","nullable":true,"metadata":{}},{"name":"meter_id","type":"string","nullable":true,"metadata":{}},{"name":"plate_expiry_date","type":"date","nullable":true,"metadata":{}},{"name":"route","type":"string","nullable":true,"metadata":{}},{"name":"rp_state_plate","type":"string","nullable":true,"metadata":{}},{"name":"ticket_number","type":"string","nullable":false,"metadata":{}},{"name":"vin","type":"string","nullable":true,"metadata":{}},{"name":"violation_code","type":"string","nullable":true,"metadata":{}},{"name":"violation_description","type":"string","nullable":true,"metadata":{}}]} 

file schema:           spark_schema 
--------------------------------------------------------------------------------
:                      created_at: OPTIONAL BINARY O:UTF8 R:0 D:1
:                      id: OPTIONAL BINARY O:UTF8 R:0 D:1
:                      updated_at: OPTIONAL BINARY O:UTF8 R:0 D:1
agency:                OPTIONAL INT32 R:0 D:1
body_style:            OPTIONAL BINARY O:UTF8 R:0 D:1
color:                 OPTIONAL BINARY O:UTF8 R:0 D:1
fine_amount:           OPTIONAL INT32 R:0 D:1
issue_date:            OPTIONAL INT32 O:DATE R:0 D:1
issue_time:            OPTIONAL INT32 R:0 D:1
latitude:              OPTIONAL INT32 O:DECIMAL R:0 D:1
location:              OPTIONAL BINARY O:UTF8 R:0 D:1
longitude:             OPTIONAL INT32 O:DECIMAL R:0 D:1
make:                  OPTIONAL BINARY O:UTF8 R:0 D:1
marked_time:           OPTIONAL BINARY O:UTF8 R:0 D:1
meter_id:              OPTIONAL BINARY O:UTF8 R:0 D:1
plate_expiry_date:     OPTIONAL INT32 O:DATE R:0 D:1
route:                 OPTIONAL BINARY O:UTF8 R:0 D:1
rp_state_plate:        OPTIONAL BINARY O:UTF8 R:0 D:1
ticket_number:         REQUIRED BINARY O:UTF8 R:0 D:0
vin:                   OPTIONAL BINARY O:UTF8 R:0 D:1
violation_code:        OPTIONAL BINARY O:UTF8 R:0 D:1
violation_description: OPTIONAL BINARY O:UTF8 R:0 D:1

row group 1:           RC:148192 TS:10503944 OFFSET:4 
--------------------------------------------------------------------------------
:                      created_at:  BINARY SNAPPY DO:0 FPO:4 SZ:607/616/1.01 VC:148192 ENC:BIT_PACKED,PLAIN_DICTIONARY,RLE ST:[min: 2019-02-28T00:16:06.329Z, max: 2019-03-02T00:20:00.249Z, num_nulls: 0]
:                      id:  BINARY SNAPPY DO:0 FPO:611 SZ:2365472/3260525/1.38 VC:148192 ENC:BIT_PACKED,PLAIN,RLE ST:[min: row-2229_y75z.ftdu, max: row-zzzs_4hta.8fub, num_nulls: 0]
:                      updated_at:  BINARY SNAPPY DO:0 FPO:2366083 SZ:602/611/1.01 VC:148192 ENC:BIT_PACKED,PLAIN_DICTIONARY,RLE ST:[min: 2019-02-28T00:16:06.329Z, max: 2019-03-02T00:20:00.249Z, num_nulls: 0]
agency:                 INT32 SNAPPY DO:0 FPO:2366685 SZ:4871/5267/1.08 VC:148192 ENC:BIT_PACKED,PLAIN_DICTIONARY,RLE ST:[min: 1, max: 58, num_nulls: 0]
body_style:             BINARY SNAPPY DO:0 FPO:2371556 SZ:36244/61827/1.71 VC:148192 ENC:BIT_PACKED,PLAIN_DICTIONARY,RLE ST:[min: , max: WR, num_nulls: 0]
color:                  BINARY SNAPPY DO:0 FPO:2407800 SZ:111267/111708/1.00 VC:148192 ENC:BIT_PACKED,PLAIN_DICTIONARY,RLE ST:[min: , max: YL, num_nulls: 0]
fine_amount:            INT32 SNAPPY DO:0 FPO:2519067 SZ:71989/82138/1.14 VC:148192 ENC:BIT_PACKED,PLAIN_DICTIONARY,RLE ST:[min: 25, max: 363, num_nulls: 63]
issue_date:             INT32 SNAPPY DO:0 FPO:2591056 SZ:20872/23185/1.11 VC:148192 ENC:BIT_PACKED,PLAIN_DICTIONARY,RLE ST:[min: 2019-02-01, max: 2019-02-27, num_nulls: 0]
issue_time:             INT32 SNAPPY DO:0 FPO:2611928 SZ:210026/210013/1.00 VC:148192 ENC:BIT_PACKED,PLAIN_DICTIONARY,RLE ST:[min: 1, max: 2359, num_nulls: 41]
latitude:               INT32 SNAPPY DO:0 FPO:2821954 SZ:508049/512228/1.01 VC:148192 ENC:BIT_PACKED,PLAIN_DICTIONARY,RLE ST:[min: 99999.0, max: 6513161.2, num_nulls: 0]
location:               BINARY SNAPPY DO:0 FPO:3330003 SZ:1251364/2693435/2.15 VC:148192 ENC:BIT_PACKED,PLAIN_DICTIONARY,PLAIN,RLE ST:[min: , max: ZOMBAR/VALERIO, num_nulls: 0]
longitude:              INT32 SNAPPY DO:0 FPO:4581367 SZ:516233/520692/1.01 VC:148192 ENC:BIT_PACKED,PLAIN_DICTIONARY,RLE ST:[min: 99999.0, max: 1941557.4, num_nulls: 0]
make:                   BINARY SNAPPY DO:0 FPO:5097600 SZ:147034/150364/1.02 VC:148192 ENC:BIT_PACKED,PLAIN_DICTIONARY,RLE ST:[min: , max: YAMA, num_nulls: 0]
marked_time:            BINARY SNAPPY DO:0 FPO:5244634 SZ:11675/17658/1.51 VC:148192 ENC:BIT_PACKED,PLAIN_DICTIONARY,RLE ST:[min: , max: 959.0, num_nulls: 0]
meter_id:               BINARY SNAPPY DO:0 FPO:5256309 SZ:172432/256692/1.49 VC:148192 ENC:BIT_PACKED,PLAIN_DICTIONARY,RLE ST:[min: , max: YO97, num_nulls: 0]
plate_expiry_date:      INT32 SNAPPY DO:0 FPO:5428741 SZ:149849/152288/1.02 VC:148192 ENC:BIT_PACKED,PLAIN_DICTIONARY,RLE ST:[min: 2000-02-01, max: 2099-12-01, num_nulls: 18624]
route:                  BINARY SNAPPY DO:0 FPO:5578590 SZ:38377/45948/1.20 VC:148192 ENC:BIT_PACKED,PLAIN_DICTIONARY,RLE ST:[min: , max: WTD, num_nulls: 0]
rp_state_plate:         BINARY SNAPPY DO:0 FPO:5616967 SZ:33281/60186/1.81 VC:148192 ENC:BIT_PACKED,PLAIN_DICTIONARY,RLE ST:[min: AB, max: XX, num_nulls: 0]
ticket_number:          BINARY SNAPPY DO:0 FPO:5650248 SZ:801039/2074791/2.59 VC:148192 ENC:BIT_PACKED,PLAIN ST:[min: 1020798376, max: 4350802142, num_nulls: 0]
vin:                    BINARY SNAPPY DO:0 FPO:6451287 SZ:64/60/0.94 VC:148192 ENC:BIT_PACKED,PLAIN_DICTIONARY,RLE ST:[min: , max: , num_nulls: 0]
violation_code:         BINARY SNAPPY DO:0 FPO:6451351 SZ:94784/131071/1.38 VC:148192 ENC:BIT_PACKED,PLAIN_DICTIONARY,RLE ST:[min: 000, max: 8942, num_nulls: 0]
violation_description:  BINARY SNAPPY DO:0 FPO:6546135 SZ:95937/132641/1.38 VC:148192 ENC:BIT_PACKED,PLAIN_DICTIONARY,RLE ST:[min: , max: YELLOW ZONE, num_nulls: 0]
> parquet-tools dump -m -c make part-00000-fc34f237-c985-4ebc-822b-87fa446f6f70.c000.snappy.parquet | head -20
BINARY make 
--------------------------------------------------------------------------------
*** row group 1 of 1, values 1 to 148192 *** 
value 1:      R:0 D:1 V:HYDA
value 2:      R:0 D:1 V:NISS
value 3:      R:0 D:1 V:NISS
value 4:      R:0 D:1 V:TOYO
value 5:      R:0 D:1 V:AUDI
value 6:      R:0 D:1 V:MERC
value 7:      R:0 D:1 V:LEX
value 8:      R:0 D:1 V:BMW
value 9:      R:0 D:1 V:GMC
value 10:     R:0 D:1 V:HOND
value 11:     R:0 D:1 V:TOYO
value 12:     R:0 D:1 V:NISS
value 13:     R:0 D:1 V:
value 14:     R:0 D:1 V:THOR
value 15:     R:0 D:1 V:DODG
value 16:     R:0 D:1 V:DODG
value 17:     R:0 D:1 V:HOND

在我的 Windows 10 x64 上,使用 WSL 没有起作用。请参考我的答案,通过源代码构建来解决这个问题。 - Contango
4
我的回答明确说明是针对 Mac OS 的。 - mropp
当我尝试运行 pip install parquet-tools 时,该工具没有 metarowcount 命令,只有 showcsvinspect。这是一个不同的工具还是它已经改变了? - Dahn
1
@Dahn,通过pip安装的版本是旧版。我建议你通过homebrew进行安装。如果你不想使用homebrew,也可以尝试使用pip install parquet-cli来获取类似功能的软件。 - mropp
23
很遗憾,自2022年7月31日起,这个自制配方已被弃用。 - Oscar Drai
显示剩余2条评论

54
我发现这个程序非常有用:https://github.com/chhantyal/parquet-cli 它可以让您在没有安装完整基础设施的情况下查看parquet文件。
只需输入:
pip install parquet-cli
parq input.parquet --head 10

27

30
在Mac上,您可以使用Homebrew安装:brew install parquet-tools。 - ronhash
1
我已经在这里上传了JAR文件(无需在项目的Github页面上糊弄有缺陷的构建说明):http://www102.zippyshare.com/v/EGBKrDuq/file.html - Aydin K.
3
如果您不想自己构建,可以从Maven网站下载jar包:http://central.maven.org/maven2/org/apache/parquet/parquet-tools/1.10.0/parquet-tools-1.10.0.jar。 - smishra
3
Maven构建不包括依赖项,因此我收到了一个错误消息 java.lang.NoClassDefFoundError: org/apache/hadoop/fs/Path - Dobes Vandermeer
1
截至2020年中,Maven Central上parquet-tools JAR的链接为https://repo1.maven.org/maven2/org/apache/parquet/parquet-tools/1.11.0/parquet-tools-1.11.0.jar。 - Denis Arnaud
显示剩余2条评论

13

默认情况下,parquet-tools 通常会查找本地文件目录,因此要将其指向hdfs,我们需要在文件路径的开头添加hdfs://。因此在您的情况下,可以这样做:

parquet-tools head hdfs://localhost/<hdfs-path> | less

我遇到了同样的问题,但对我来说它运行得很好。没有必要先在本地下载文件。


10

DuckDB有一个CLI工具(适用于Linux、Windows和macOS的预构建二进制文件),可以在命令行中使用它来查询Parquet数据

PS C:\Users\nsuser\dev\standalone_executable_binaries> ./duckdb
v0.5.1 7c111322d
Enter ".help" for usage hints.
Connected to a transient in-memory database.
Use ".open FILENAME" to reopen on a persistent database.

使用 SQL 查询读取 parquet 数据

D SELECT * FROM READ_PARQUET('C:\Users\nsuser\dev\sample_files\userdata1.parquet') limit 3;
┌─────────────────────┬────┬────────────┬───────────┬─────────────────────────┬────────┬────────────────┬──────────────────┬───────────┬───────────┬───────────┬─────────────────────┬──────────┐
│  registration_dttm  │ id │ first_name │ last_name │          email          │ gender │   ip_address   │        cc        │  country  │ birthdate │  salary   │        title        │ comments │
├─────────────────────┼────┼────────────┼───────────┼─────────────────────────┼────────┼────────────────┼──────────────────┼───────────┼───────────┼───────────┼─────────────────────┼──────────┤
│ 2016-02-03 07:55:291  │ Amanda     │ Jordan    │ ajordan0@com.com        │ Female │ 1.197.201.26759521864920116 │ Indonesia │ 3/8/197149756.53  │ Internal Auditor    │ 1E+02    │
│ 2016-02-03 17:04:032  │ Albert     │ Freeman   │ afreeman1@is.gd         │ Male   │ 218.111.175.34 │                  │ Canada    │ 1/16/1968150280.17 │ Accountant IV       │          │
│ 2016-02-03 01:09:313  │ Evelyn     │ Morgan    │ emorgan2@altervista.org │ Female │ 7.161.136.946767119071901597 │ Russia    │ 2/1/1960144972.51 │ Structural Engineer │          │
└─────────────────────┴────┴────────────┴───────────┴─────────────────────────┴────────┴────────────────┴──────────────────┴───────────┴───────────┴───────────┴─────────────────────┴──────────┘

阅读 Parquet 模式。
D DESCRIBE SELECT * FROM READ_PARQUET('C:\Users\nsuser\dev\sample_files\userdata1.parquet');
OR
D SELECT * FROM PARQUET_SCHEMA('C:\Users\nsuser\dev\sample_files\userdata1.parquet');
┌───────────────────┬─────────────┬──────┬─────┬─────────┬───────┐
│    column_name    │ column_type │ null │ key │ default │ extra │
├───────────────────┼─────────────┼──────┼─────┼─────────┼───────┤
│ registration_dttm │ TIMESTAMP   │ YES  │     │         │       │
│ id                │ INTEGER     │ YES  │     │         │       │
│ first_name        │ VARCHAR     │ YES  │     │         │       │
│ birthdate         │ VARCHAR     │ YES  │     │         │       │
│ salary            │ DOUBLE      │ YES  │     │         │       │
└───────────────────┴─────────────┴──────┴─────┴─────────┴───────┘

读取 Parquet 元数据和统计信息。

D SELECT row_group_id, row_group_num_rows, compression, stats_min, stats_max, stats_null_count FROM PARQUET_METADATA('C:\Users\nsuser\dev\sample_files\userdata1.parquet');
┌──────────────┬────────────────────┬──────────────┬─────────────────────┬─────────────────────┬──────────────────┐
│ row_group_id │ row_group_num_rows │ compression  │      stats_min      │      stats_max      │ stats_null_count │
├──────────────┼────────────────────┼──────────────┼─────────────────────┼─────────────────────┼──────────────────┤
│ 01000               │ UNCOMPRESSED │ 2016-02-03 22:59:122016-02-03 20:51:310                │
│ 01000               │ UNCOMPRESSED │ 110000                │
│ 01000               │ UNCOMPRESSED │ "Bonaire            │ Zimbabwe            │ 0                │
│ 0            │ 1000               │ UNCOMPRESSED │                     │ 9/9/1981            │ 0                │
│ 0            │ 1000               │ UNCOMPRESSED │ 12380.49            │ 286592.99           │ 68               │
└──────────────┴────────────────────┴──────────────┴─────────────────────┴─────────────────────┴──────────────────┘

替代方案:

parquet-cli 是一个轻量级的Python替代方案。

pip install parquet-cli          //installs via pip
parq filename.parquet            //view meta data
parq filename.parquet --schema   //view the schema
parq filename.parquet --head 10  //view top n rows

1
哦,太好了 - 感谢您提供的截图和示例,让我尝试duckdb - WestCoastProjects
感谢您指向DuckDB。它们已经在我的视线范围内,但现在我有了真正使用它的理由。 - Saïd

9

实际上,我发现pandas已经支持parquet文件格式,只要安装了pyarrow或fastparquet作为其后端。请查看read_parquet

import pandas as pd

df = pd.read_parquet('your-file.parquet')

df.head(10)
...

可能来晚了,但我刚刚学到pyarrow已经支持读取parquet文件格式,并且相当强大。很有可能您已经安装了pyarrow和pandas,因此您可以像这样读取parquet文件。
from pyarrow import parquet
import pandas

p = parquet.read_table('/path/to/your/xxxxx.parquet')
df = p.to_pandas()

df.head(10)
...

5

如果您正在使用HDFS,以下命令非常有用,因为它们经常被使用(留在这里供将来参考):

hadoop jar parquet-tools-1.9.0.jar schema hdfs://path/to/file.snappy.parquet
hadoop jar parquet-tools-1.9.0.jar head -n5 hdfs://path/to/file.snappy.parquet

顺便提一下,parquet-tools-1.9.0.jar 可以从 Maven 仓库中获取:https://repo1.maven.org/maven2/org/apache/parquet/parquet-tools/1.9.0/parquet-tools-1.9.0.jar - Zhigong Li

2
如果您使用Docker,您也可以像这样做:
docker run -ti -v C:\file.parquet:/tmp/file.parquet nathanhowell/parquet-tools cat /tmp/file.parquet

1
在 Windows 10 x64 上,尝试使用 Parq
choco install parq

这会将所有内容安装到当前目录中。您需要手动将此目录添加到路径中,或从该目录内运行parq.exe
我的另一个答案是从源代码构建parquet-reader。这个实用程序似乎做了同样的工作。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接