目录
About
Install
macOS Homebrew
macOS、Linux和WSL上的二进制文件
Windows上的二进制文件(非WSL)
从源代码生成和安装
Usage
Pretty print
dsq的管道数据
多个文件和连接
无需查询即可将数据转换为JSON
嵌套在对象中的对象数组
嵌套对象值
Nested arrays
REGEXP
Standard Library
输出列顺序
转储推断架构
Caching
Interactive REPL
转换CSV和TSV文件中的数字
Supported Data Types
Engine
Comparisons
Benchmark
Notes
About
这是DataStation(GUI)的CLI配套工具,用于对数据文件运行SQL查询。因此,如果您想要这个GUI版本,请查看DataStation。
Install
每个版本都提供了amd64(x86_64)的二进制文件。
macOS Homebrew
$ brew install dsq
macOS、Linux和WSL上的二进制文件
在macOS、Linux和WSL上,您可以运行以下操作:
$ curl -LO "https://github.com/multiprocessio/dsq/releases/download/0.20.2/dsq-$(uname -s | awk '{ print tolower($0) }')-x64-0.20.2.zip" $ unzip dsq-*-0.20.2.zip $ sudo mv dsq /usr/local/bin/dsq
或者从发布页面手动安装,解压并将
Windows上的二进制文件(非WSL)
下载最新的Windows版本,解压它,并将
从源代码生成和安装
如果您在另一个平台或架构上,或者想要获取最新版本,可以使用Go1.18+:
$ go install github.com/multiprocessio/dsq@latest
Usage
您可以将数据管道传输到
如果要传递文件,则其内容类型必须具有通常的扩展名。
For example:
$ dsq testdata.json "SELECT * FROM {} WHERE x > 10"
Or:
$ dsq testdata.ndjson "SELECT name, AVG(time) FROM {} GROUP BY name ORDER BY AVG(time) DESC"
Pretty print
默认情况下
$ dsq testdata/userdata.parquet 'select count(*) from {}' [{"count(*)":1000} ]
如果您想要更漂亮的JSON,可以通过管道
$ dsq testdata/userdata.parquet 'select count(*) from {}' | jq [ { "count(*)": 1000 } ]
或者,您可以使用
$ dsq --pretty testdata/userdata.parquet 'select count(*) from {}' +----------+ | count(*) | +----------+ | 1000 | +----------+
dsq的管道数据
当将数据传输到
For example:
$ cat testdata.csv | dsq -s csv "SELECT * FROM {} LIMIT 1"
Or:
$ cat testdata.parquet | dsq -s parquet "SELECT COUNT(1) FROM {}"
多个文件和连接
您可以将多个文件传递给DSQ。只要支持有效格式的数据文件,就可以对所有文件作为表运行SQL。每个表都可以通过字符串
例如,这连接了两个不同来源类型的数据集(CSV和JSON)。
$ dsq testdata/join/users.csv testdata/join/ages.json "select {0}.name, {1}.age from {0} join {1} on {0}.id = {1}.id" [{"age":88,"name":"Ted"}, {"age":56,"name":"Marjory"}, {"age":33,"name":"Micah"}]
由于
$ dsq testdata/join/users.csv testdata/join/ages.json "select u.name, a.age from {0} u join {1} a on u.id = a.id" [{"age":88,"name":"Ted"}, {"age":56,"name":"Marjory"}, {"age":33,"name":"Micah"}]
无需查询即可将数据转换为JSON
作为
For example:
$ dsq testdata.csv [{...some csv data...},{...some csv data...},...]
嵌套在对象中的对象数组
DataStation和
例如,如果您有以下数据:
$ cat api-results.json { "data": { "data": [ {"id": 1, "name": "Corah"}, {"id": 3, "name": "Minh"} ] }, "total": 2 }
您需要告诉
$ dsq --pretty api-results.json 'SELECT * FROM {0, "data.data"} ORDER BY id DESC' +----+-------+ | id | name | +----+-------+ | 3 | Minh | | 1 | Corah | +----+-------+
如果只有一个表,也可以使用速记
$ dsq --pretty api-results.json 'SELECT * FROM {"data.data"} ORDER BY id DESC' +----+-------+ | id | name | +----+-------+ | 3 | Minh | | 1 | Corah | +----+-------+
可以对路径使用单引号或双引号。
多张Excel工作表
包含多个工作表的Excel文件存储为一个对象,键为工作表名称,值为作为对象数组的工作表数据。
如果您有一个Excel文件,其中包含两个名为
$ dsq data.xlsx 'SELECT COUNT(1) FROM {"Sheet2"}'
限制:嵌套数组
不能指定通过数组的路径,只能指定对象。
嵌套对象值
举个例子最简单。假设您有以下名为
$ cat user_addresses.json [ {"name": "Agarrah", "location": {"city": "Toronto", "address": { "number": 1002 }}}, {"name": "Minoara", "location": {"city": "Mexico City", "address": { "number": 19 }}}, {"name": "Fontoon", "location": {"city": "New London", "address": { "number": 12 }}} ]
可以按如下方式查询嵌套字段:
$ dsq user_addresses.json 'SELECT name, "location.city" FROM {}'
如果需要消除表格的歧义:
$ dsq user_addresses.json 'SELECT name, {}."location.city" FROM {}'
Caveat: PowerShell, CMD.exe
在PowerShell和CMD.exe上,必须用反斜杠转义内部双引号:
> dsq user_addresses.json 'select name, "location.city" from {}' [{"location.city":"Toronto","name":"Agarrah"}, {"location.city":"Mexico City","name":"Minoara"}, {"location.city":"New London","name":"Fontoon"}]
解释了嵌套对象
嵌套对象被折叠,它们的新列名成为
限制:整个对象检索
您无法查询整个对象,必须请求生成标量值的特定路径。
例如,在上面的
$ dsq user_addresses.json 'SELECT name, {}."location" FROM {}'
因为
Nested arrays
嵌套数组存储在SQLite中时会转换为JSON字符串。由于SQLite支持查询JSON字符串,您可以将该数据作为结构化数据访问,即使它是一个字符串。
如果在
[ {"field1": [1]}, {"field1": [2]}, ]
您可以请求整个字段:
$ dsq fields.json "SELECT field1 FROM {}" | jq [ { "field1": "[1]" }, { "field1": "[2]", } ]
JSON operators
可以使用SQL JSON运算符获取数组中的第一个值。
$ dsq fields.json "SELECT field1->0 FROM {}" | jq [ { "field1->0": "1" }, { "field1->0": "2" } ]
REGEXP
由于DataStation和
$ dsq user_addresses.json "SELECT * FROM {} WHERE name REGEXP 'A.*'" [{"location.address.number":1002,"location.city":"Toronto","name":"Agarrah"}]
Standard Library
dsq注册go-sqlite3-stdlib,因此您可以访问许多不属于SQLite基的统计信息、url、数学、字符串和regexp函数。
查看所有可用扩展功能的项目文档。
输出列顺序
当发出JSON(即没有
如果顺序对你很重要,你可以用
使用
转储推断架构
对于任何受支持的文件,您都可以转储推断出的模式,而不是转储数据或运行SQL查询。为此,设置
推断的模式非常简单,只支持JSON类型。如果底层格式(如Parquet)支持finer-grained数据类型(如int64),则这不会显示在推断的模式中。它将显示为
For example:
$ dsq testdata/avro/test_data.avro --schema --pretty Array of Object of birthdate of string cc of Varied of Object of long of number or Unknown comments of string country of string email of string first_name of string gender of string id of number ip_address of string last_name of string registration_dttm of string salary of Varied of Object of double of number or Unknown title of string
通过在设置
Caching
有时,您希望对不经常更改的数据集进行一些探索。通过打开
启用缓存后,DataStation将计算您指定的所有文件的SHA1总和。如果总和发生变化,则它将重新导入所有文件。否则,当运行带有缓存标志的其他查询时,将重用该现有数据库,而不会重新导入文件。
由于DataStation上没有缓存时使用in-memory数据库,因此打开缓存时的初始查询可能比关闭缓存时稍长。不过,后续查询将大大加快(对于大型数据集)。
例如,在此查询上使用缓存的第一次运行可能需要30秒:
$ dsq some-large-file.json --cache 'SELECT COUNT(1) FROM {}'
但是,当您运行另一个查询时,可能只需要1s。
$ dsq some-large-file.json --cache 'SELECT SUM(age) FROM {}'
不是因为我们缓存了任何结果,而是因为我们缓存了将文件导入SQLite的过程。
因此,即使您更改了查询,只要文件没有更改,缓存也是有效的。
为了使其永久化,您可以在您的环境中导出
Interactive REPL
使用
$ dsq some-large-file.json -i dsq> SELECT COUNT(1) FROM {}; +----------+ | COUNT(1) | +----------+ | 1000 | +----------+ (1 row) dsq> SELECT * FROM {} WHERE NAME = 'Kevin'; (0 rows)
转换CSV和TSV文件中的数字
CSV和TSV文件不允许指定其中包含的单个值的类型。默认情况下,所有值都被视为字符串。
这可能导致查询中出现意外结果。考虑以下示例:
$ cat scores.csv name,score Fritz,90 Rainer,95.2 Fountainer,100 $ dsq scores.csv "SELECT * FROM {} ORDER BY score" [{"name":"Fountainer","score":"100"}, {"name":"Fritz","score":"90"}, {"name":"Rainer","score":"95.2"}]
注意
使用
$ dsq ~/scores.csv --convert-numbers "SELECT * FROM {} ORDER BY score" [{"name":"Fritz","score":90}, {"name":"Rainer","score":95.2}, {"name":"Fountainer","score":100}]
注意现在分数是如何作为数字导入的,以及结果集中的记录是如何按其数值排序的。还请注意,JSON结果中不再引用单个分数。
为了使其永久化,您可以在您的环境中导出
Supported Data Types
Name | File Extension(s) | Mime Type | Notes |
---|---|---|---|
CSV | |||
TSV | |||
JSON | 必须是对象数组或对象数组的路径。 | ||
Newline-delimited JSON | |||
Concatenated JSON | |||
ORC | |||
Parquet | |||
Avro | |||
YAML | |||
Excel | 如果有多张图纸,则必须指定图纸路径。 | ||
ODS | 如果有多张图纸,则必须指定图纸路径。 | ||
Apache Error Logs | NA | 当前仅在管道中工作。 | |
Apache Access Logs | NA | 当前仅在管道中工作。 | |
Nginx Access Logs | NA | 当前仅在管道中工作。 | |
LogFmt Logs | NA | 当前仅在管道中工作。 |
Engine
在后台,dsq使用DataStation作为库,在后台,DataStation使用SQLite支持对任意(结构化)数据的此类SQL查询。
Comparisons
Name | Link | Caching | Engine | Supported File Types | Binary Size |
---|---|---|---|---|---|
dsq | Here | Yes | SQLite | CSV、TSV、JSON的一些变体、拼花地板、Excel、ODS(OpenOffice Calc)、ORC、Avro、YAML、日志 | 49M |
q | http://harelba.github.io/q/ | Yes | SQLite | CSV, TSV | 82M |
textql | https://github.com/dinedal/textql | No | SQLite | CSV, TSV | 7.3M |
octoql | https://github.com/cube2222/octosql | No | Custom engine | JSON, CSV, Excel, Parquet | 18M |
csvq | https://github.com/mithrandie/csvq | No | Custom engine | CSV | 15M |
sqlite-utils | https://github.com/simonw/sqlite-utils | No | SQLite | CSV, TSV | 不适用,不是一个二进制文件 |
trdsql | https://github.com/noborus/trdsql | No | SQLite、MySQL或PostgreSQL | JSON、TSV、LTSV、TBLN、CSV的一些变体 | 14M |
spysql | https://github.com/dcmoura/spyql | No | Custom engine | CSV, JSON, TEXT | 不适用,不是一个二进制文件 |
duckdb | https://github.com/duckdb/duckdb | ? | Custom engine | CSV, Parquet | 35M |
Not included:
- clickhouse-local:这里列出的所有工具中速度最快的,但它太大了(超过2GB),不能合理地被认为是任何环境的好工具
- sqlite3:需要多个命令来接收CSV,对于one-liners来说并不太好
- datafusion-cli:非常快(仅比clickhouse-local慢),但需要多个命令来接收CSV,因此对于one-liners来说并不太好
Benchmark
该基准测试于2022年6月19日运行。它在OVH上的专用裸机实例上运行,具有:
- 64 GB DDR4 ECC 2133 MHz
- 软RAID中的2x450 GB SSD NVMe
- 英特尔至强E3-1230v6-4c/8t-3.5GHz/3.9 GHz
它对well-known纽约黄色出租车出行数据集运行
脚本在这里。它是octosql开发人员运行的基准测试的一种修改。
Program | Version | Mean ▼显示 | Min ▼显示 | Max ▼显示 | Relative |
---|---|---|---|---|---|
dsq | 0.20.1(缓存打开) | 1.151 ± 0.010 | 1.131 | 1.159 | 1.00 |
duckdb | 0.3.4 | 1.723 ± 0.023 | 1.708 | 1.757 | 1.50 ± 0.02 |
octosql | 0.7.3 | 2.005 ± 0.008 | 1.991 | 2.015 | 1.74 ± 0.02 |
q | 3.1.6(缓存打开) | 2.028 ± 0.010 | 2.021 | 2.055 | 1.76 ± 0.02 |
sqlite3 * | 3.36.0 | 4.204 ± 0.018 | 4.177 | 4.229 | 3.64 ± 0.04 |
trdsql | 0.10.0 | 12.972 ± 0.225 | 12.554 | 13.392 | 11.27 ± 0.22 |
dsq | 0.20.1 (default) | 15.030 ± 0.086 | 14.895 | 15.149 | 13.06 ± 0.13 |
textql | fca00ec | 19.148 ± 0.183 | 18.865 | 19.500 | 16.63 ± 0.21 |
spyql | 0.6.0 | 16.985 ± 0.105 | 16.854 | 17.161 | 14.75 ± 0.16 |
q | 3.1.6 (default) | 24.061 ± 0.095 | 23.954 | 24.220 | 20.90 ± 0.20 |
*虽然dsq和q构建在sqlite3之上,但sqlite3中没有内置的方法来缓存摄取的文件,而无需编写脚本
Not included:
- clickhouse-local:比任何一个都快,但超过2GB,因此不是合理的general-purposeCLI
- datafusion-cli:只比clickhouse-local慢,但需要多个命令来接收CSV,不能执行one-liners
- sqlite-utils:需要几分钟才能完成
Notes
OctoSQL、duckdb和SpyQL实现了自己的SQL引擎。dsq、q、trdsql和textql将数据复制到SQLite中,并依赖SQLite引擎执行查询。
实现自己的SQL引擎的工具在1)摄取和2)作用于数据子集(例如有限列或有限行)的查询方面可以做得更好。这些工具实现了SQL的ad-hoc子集,这些子集可能缺失或与您喜欢的语法不同。另一方面,依赖SQLite的工具具有提供well-tested和well-documentedSQL引擎的优势。DuckDB与众不同,因为它背后有一家专注的公司。
dsq在SQLite内置函数的基础上还附带了许多有用的函数(例如best-effort日期解析、URL解析/提取、统计函数等)。
转自项目内 README.md
multiprocessio/dsq: Commandline tool for running SQL queries against JSON, CSV, Excel, Parquet, and more. (github.com)https://github.com/multiprocessio/dsq