这个版本按发版说明的说法性能是clickhouse的3倍,不太相信。
以下按照存储库 https://github.com/malisper/pgrust 介绍的步骤安装,最大的改变是包含initdb和psql, 不需要借用postgresql的。
-
下载二进制包并解压缩
kylin@kylin-aaa:/data/i$ wget https://pgrust.com/downloads/v0.4-beta/pgrust-0.4-beta-linux-aarch64.tar.gz
2026-10-23 14:46:49 (838 KB/s) - 已保存 "pgrust-0.4-beta-linux-aarch64.tar.gz" [31221024/31221024])
root@kylin-aaa:/par# tar xf pgrust-0.4-beta-linux-aarch64.tar.gz
root@kylin-aaa:/par# mv pgrust-0.4-beta-linux-aarch64 pgrust04b
root@kylin-aaa:/par# cd pgrust04b -
初始化数据库
root@kylin-aaa:/par/pgrust04b# bin/initdb -D /tmp/pgrust-data --no-locale --encoding UTF8 -U postgres
The files belonging to this database system will be owned by user "root".
This user must also own the server process.The database cluster will be initialized with locale "C".
The default database encoding has accordingly been set to "UTF8".
The default text search configuration will be set to "english".Data page checksums are enabled.
creating directory /tmp/pgrust-data ... ok
creating subdirectories ... ok
selecting dynamic shared memory implementation ... posix
selecting default "max_connections" ... 20
selecting default "shared_buffers" ... 400kB
selecting default time zone ... Etc/UTC
creating configuration files ... ok
running bootstrap script ... "root" execution of the PostgreSQL server is not permitted.
The server must be started under an unprivileged user ID to prevent
possible system security compromise. See the documentation for
more information on how to properly start the server.initdb: error: child process exited with exit code 1
initdb: removing data directory "/tmp/pgrust-data"
不允许用root用户,改用postgres用户
root@kylin-aaa:/par/pgrust04b# groupadd postgres
groupadd: group 'postgres' already exists
root@kylin-aaa:/par/pgrust04b# su - postgres
postgres@kylin-aaa:~$ cd /par/pgrust04b
postgres@kylin-aaa:/par/pgrust04b$ bin/initdb -D /tmp/pgrust-data --no-locale --encoding UTF8 -U postgres
The files belonging to this database system will be owned by user "postgres".
This user must also own the server process.
The database cluster will be initialized with locale "C".
The default database encoding has accordingly been set to "UTF8".
The default text search configuration will be set to "english".
Data page checksums are enabled.
creating directory /tmp/pgrust-data ... ok
creating subdirectories ... ok
selecting dynamic shared memory implementation ... posix
selecting default "max_connections" ... 100
selecting default "shared_buffers" ... 128MB
selecting default time zone ... Etc/UTC
creating configuration files ... ok
running bootstrap script ... 2026-10-23 07:24:23.439 UTC [206] LOG: raised open file limit from 1024 to 1048576 (hard limit 1048576)
2026-10-23 07:24:23.452 UTC [206] LOG: gravity: columnar catalog loaded: 0 relations, 0 generations, 0 parts, sections 0 complete / 0 completed in 0 us (0 bytes held), 0 errors, 0 us, part fds 0 open of 16
ok
performing post-bootstrap initialization ... 2026-10-23 07:24:23.656 UTC [207] LOG: raised open file limit from 1024 to 1048576 (hard limit 1048576)
2026-10-23 07:24:23.670 UTC [207] LOG: gravity: columnar catalog loaded: 0 relations, 0 generations, 0 parts, sections 0 complete / 0 completed in 0 us (0 bytes held), 0 errors, 0 us, part fds 0 open of 16
2026-10-23 07:24:23.681 UTC [207] LOG: gravity: grant pool armed at 1024 MiB, 0 statements in flight (memory limit 7706 MiB, mapped 47339 MiB, address-space limit 0 MiB, kept for backends 0 MiB, shared_buffers 128 MiB, a statement's regions 16 MiB + tables 8 MiB, mode Estimate, small lane 64 MiB)
2026-10-23 07:24:23.681 UTC [207] STATEMENT: REVOKE ALL ON pg_authid FROM public;
ok
syncing data to disk ... ok
initdb: warning: enabling "trust" authentication for local connections
You can change this by editing pg_hba.conf or using the option -A, or
--auth-local and --auth-host, the next time you run initdb.
Success. You can now start the database server using:
/par/pgrust04b/bin/postgres -D /tmp/pgrust-data
-
按照前面的提示输入启动数据库
postgres@kylin-aaa:/par/pgrust04b$ /par/pgrust04b/bin/postgres -D /tmp/pgrust-data
2026-10-23 07:24:44.297 UTC [214] LOG: cost profile: measured in 159 ms, kept in /home/postgres/.cache/pgrust/cost-profile/aarch64-unknown-l1d64k-l2512k-smt1-vd5454b46bb75c69c.tsv; host aarch64-unknown-l1d64k-l2512k-smt1-vd5454b46bb75c69c; ratios to the reference: read 2.375, gather 2, check 2.625, miss 1, update 2.25, sort 1.625; anchors ns: read 0.213, gather 1.117, check 0.476, miss 107.814, update 2.082, sort 21.907
2026-10-23 07:24:44.335 UTC [214] LOG: raised open file limit from 1024 to 1048576 (hard limit 1048576)
2026-10-23 07:24:44.406 UTC [214] LOG: starting pgrust 0.4-beta, build 20911cc (PostgreSQL 18.6 compatible)
2026-10-23 07:24:44.406 UTC [214] LOG: regexp engines: re2+spencer (regex_engine=auto dispatches compatible patterns to re2)
2026-10-23 07:24:44.407 UTC [214] LOG: listening on IPv4 address "127.0.0.1", port 5432
2026-10-23 07:24:44.414 UTC [214] LOG: listening on Unix socket "/tmp/.s.PGSQL.5432"
pgrust: cpu affinity: 8 workers on cpus 0-7 (gang mirrored; standbys pool-set)
2026-10-23 07:24:44.485 UTC [214] LOG: global allocator: hearth (this architecture's default: Hearth on Linux aarch64 and x86_64, mimalloc elsewhere; PGRUST_ALLOCATOR=mimalloc at start turns it off)
2026-10-23 07:24:44.496 UTC [1010] LOG: io_uring buffer reads unavailable (io_uring_setup: errno 1); falling back to posix_fadvise readahead
2026-10-23 07:24:44.496 UTC [1002] LOG: database system was shut down at 2026-10-23 07:24:24 UTC
WARNING: pagegive: the thread stack pin failed (errno 12); RLIMIT_MEMLOCK soft 65536 hard 65536: this thread's exit may give its whole stack reservation back to the kernel
2026-10-23 07:24:44.532 UTC [1002] LOG: gravity: columnar catalog loaded: 0 relations, 0 generations, 0 parts, sections 0 complete / 0 completed in 0 us (0 bytes held), 0 errors, 0 us, part fds 0 open of 16
2026-10-23 07:24:44.626 UTC [1028] LOG: gravity: code cache warmed in 5127 us
2026-10-23 07:24:44.684 UTC [1028] LOG: gravity: process image warmed (64 MB), 1 databases to warm (no columnar relation), 63035 us
2026-10-23 07:24:44.710 UTC [1030] LOG: gravity: catalog pages warmed for database 5: 0 relations, 0 attributes, 258 catalogs / 818 blocks, 0 part lists, image 0 MB, 21776 us
2026-10-23 07:24:44.711 UTC [214] LOG: database system is ready to accept connections
2026-10-23 07:24:45.503 UTC [214] LOG: memory watchdog: armed: limit=7706 MB (source=physical memory; no cgroup v2 limit, pgrust.memory_watchdog_limit is 0) tiers=80%/90%/95% interval=1000 ms -
打开另外一个终端,用psql连接pgrust数据库
root@kylin-aaa:/par/pgrust04b# bin/psql -h /tmp -p 5432 -U postgres
psql (18.6)
Type "help" for help.postgres=# select version();
versionPostgreSQL 18.6 (pgrust 0.4-beta, build 20911cc) on aarch64-unknown-linux-gnu, 64-bit
(1 row)
下面是常见功能性能测试
postgres=# \timing on
Timing is on.
postgres=# select count(*) from generate_series(1,1000000)t(i);
count
---------
1000000
(1 row)
Time: 4.205 ms
postgres=# select count(*) from generate_series(1,10000000)t(i) group by round(log10(i));
count
---------
285
3
2846050
6837723
284605
28
2846
28460
(8 rows)
Time: 553.967 ms
postgres=# select distinct round(log10(i)) from generate_series(1,10000000)t(i);
round
-------
2
0
6
7
5
1
3
4
(8 rows)
Time: 566.149 ms
我习惯用的递归求解数独SQL,postgres语法版本
sql
WITH RECURSIVE
input(sud) AS (
VALUES('.....1..7....6..2.8..9..3...954....3..3...4..4......8......7..6.1..2....5..3..9..')
),
digits(z, lp) AS (
VALUES('1', 1)
UNION ALL SELECT
CAST(lp+1 AS TEXT), lp+1 FROM digits WHERE lp<9
),
x(s, ind) AS (
SELECT sud, position('.'in sud ) FROM input
UNION ALL
SELECT
substr(s, 1, ind-1) || z || substr(s, ind+1),
position('.' in substr(s, 1, ind-1) || z || substr(s, ind+1) )
FROM x, digits AS z
WHERE ind>0
AND NOT EXISTS (
SELECT 1
FROM digits AS lp
WHERE z.z = substr(s, ((ind-1)/9)*9 + lp, 1)
OR z.z = substr(s, ((ind-1)%9) + (lp-1)*9 + 1, 1)
OR z.z = substr(s, (((ind-1)/3) % 3) * 3
+ ((ind-1)/27) * 27 + lp
+ ((lp-1) / 3) * 6, 1)
)
)
SELECT s FROM x WHERE ind=0;
postgres=# \i ../sudopghd.txt
s
-----------------------------------------------------------------------------------
346251897759863124821974365195486273683712459472539681238197546914625738567348912
(1 row)
Time: 14867.849 ms (00:14.868)
高精度计算阶乘
postgres=# with recursive t as (select 1 a,'1'::decimal b union all select a+1,b::decimal*(a+1)::decimal from t where a<10000)select length(b::varchar)from t where a=10000;
length
--------
35660
(1 row)
Time: 359.945 ms
postgres=# with recursive t as (select 1 a,'1'::decimal b union all select a+1,b::decimal*(a+1)::decimal from t where a<20000)select length(b::varchar)from t where a=20000;
ERROR: could not allocate temporary file of 268435456 bytes for a Gravity owner region: No space left on device (os error 28)
Time: 1603.063 ms (00:01.603)
用duckdb 2.0版对比
wget http://install.duckdb.org/v2.0.0/duckdb-cli-linux-arm64.tar.gz -O duckdb20.tar.gz
root@kylin-aaa:/par# ./duckdb20
DuckDB v2.0.0 (Cyanoptera)
Enter ".help" for usage hints.
memory D .timer on
memory D select count(*) from generate_series(1,10000000)t(i) group by round(log10(i));
┌──────────────┐
│ count_star() │
│ int64 │
├──────────────┤
│ 3 │
│ 285 │
│ 2846 │
│ 28 │
│ 2846050 │
│ 284605 │
│ 6837723 │
│ 28460 │
└──────────────┘
Run Time (s): real 0.356 user 0.360000 sys 0.000000
memory D select distinct round(log10(i)) from generate_series(1,10000000)t(i);
┌─────────────────┐
│ round(log10(i)) │
│ double │
├─────────────────┤
│ 0.0 │
│ 2.0 │
│ 3.0 │
│ 4.0 │
│ 1.0 │
│ 6.0 │
│ 5.0 │
│ 7.0 │
└─────────────────┘
Run Time (s): real 0.328 user 0.328000 sys 0.012000
memory D
memory D .read sudoduckhd.txt
┌───────────────────────────────────────────────────────────────────────────────────┐
│ s │
│ varchar │
├───────────────────────────────────────────────────────────────────────────────────┤
│ 346251897759863124821974365195486273683712459472539681238197546914625738567348912 │
└───────────────────────────────────────────────────────────────────────────────────┘
Run Time (s): real 14.444 user 15.612000 sys 1.272000
用同样采用rust语言编写的turso对比
root@kylin-aaa:/par# turso090/tursodb
Turso v0.9.0-pre.1
Enter ".help" for usage hints.
Did you know that Turso supports a built-in MCP server? Type .manual mcp to learn more.
Connected to a transient in-memory database.
Use ".open FILENAME" to reopen on a persistent database
turso> .timer on
turso> .read sudohd.txt
┌───────────────────────────────────────────────────────────────────────────────────┐
│ s │
├───────────────────────────────────────────────────────────────────────────────────┤
│ 346251897759863124821974365195486273683712459472539681238197546914625738567348912 │
└───────────────────────────────────────────────────────────────────────────────────┘
Command stats:
----------------------------
total: 21.97244058 s (this includes parsing/coloring of cli app)
query execution stats:
----------------------------
Execution: avg=10.97795596 s, total=21.95591192 s
I/O: No samples available
用sqlite 3.53.4对比
root@kylin-aaa:/par# ./sqlite3
SQLite version 3.53.4 2026-07-24 19:02:57
Enter ".help" for usage hints.
Connected to a transient in-memory database.
Use ".open FILENAME" to reopen on a persistent database.
sqlite> .timer on
sqlite> .read sudohd.txt
╭─────────────────────────────────────────────────────────────────────────────────────╮
│ s │
╞═════════════════════════════════════════════════════════════════════════════════════╡
│ '346251897759863124821974365195486273683712459472539681238197546914625738567348912' │
╰─────────────────────────────────────────────────────────────────────────────────────╯
Run Time: real 8.914416 user 8.888000 sys 0.012000
sqlite> select count(*) from generate_series(1,10000000) group by round(log(value));
╭──────────╮
│ count(*) │
╞══════════╡
│ 3 │
│ 28 │
│ 285 │
│ 2846 │
│ 28460 │
│ 284605 │
│ 2846050 │
│ 6837723 │
╰──────────╯
Run Time: real 5.585107 user 4.956000 sys 0.236000
========================
sqlite> .exit
用duckdb main分支的2.1 alpha对比
wget https://artifacts.duckdb.org/latest/duckdb-cli-linux-arm64.tar.gz -O duckdb-cli-linux-arm64-261022a.tar.gz
root@kylin-aaa:/par# ./duckdb1022a
DuckDB v2.1.0-alpha49503 (Unknown Version)
Enter ".help" for usage hints.
memory D .timer on
memory D select count(*) from generate_series(1,10000000)t(i) group by round(log10(i));
┌──────────────┐
│ count_star() │
│ int64 │
├──────────────┤
│ 3 │
│ 284605 │
│ 6837723 │
│ 28 │
│ 2846050 │
│ 28460 │
│ 285 │
│ 2846 │
└──────────────┘
Run Time (s): real 0.343 user 0.344000 sys 0.000000
memory D select distinct round(log10(i)) from generate_series(1,10000000)t(i);
┌─────────────────┐
│ round(log10(i)) │
│ double │
├─────────────────┤
│ 0.0 │
│ 1.0 │
│ 6.0 │
│ 5.0 │
│ 7.0 │
│ 2.0 │
│ 3.0 │
│ 4.0 │
└─────────────────┘
Run Time (s): real 0.311 user 0.312000 sys 0.000000
memory D .read sudoduckhd.txt
┌───────────────────────────────────────────────────────────────────────────────────┐
│ s │
│ varchar │
├───────────────────────────────────────────────────────────────────────────────────┤
│ 346251897759863124821974365195486273683712459472539681238197546914625738567348912 │
└───────────────────────────────────────────────────────────────────────────────────┘
Run Time (s): real 8.478 user 9.764000 sys 1.020000
memory D with recursive t as (select 1 a,'1'::bignum b union all select a+1,b::bignum*(a+1)::bignum from t where a<10000)select length(b::varchar)from t where a=10000;
┌────────────────────────────┐
│ length(CAST(b AS VARCHAR)) │
│ int64 │
├────────────────────────────┤
│ 35660 │
└────────────────────────────┘
Run Time (s): real 0.536 user 1.052000 sys 0.020000
memory D
memory D with recursive t as (select 1 a,'1'::bignum b union all select a+1,b::bignum*(a+1)::bignum from t where a<20000)select length(b::varchar)from t where a=20000;
┌────────────────────────────┐
│ length(CAST(b AS VARCHAR)) │
│ int64 │
├────────────────────────────┤
│ 77338 │
└────────────────────────────┘
Run Time (s): real 1.839 user 1.800000 sys 0.036000
总结
| 项目 | pgrust 0.4beta | duckdb 2.0 | duckdb 2.1alpha | turso 0.9 | SQLite 3.53.4 |
|---|---|---|---|---|---|
| sum group by | 0.553 | 0.356 | 0.343 | 未测 | 5.585 |
| distinct | 0.566 | 0.328 | 0.311 | 未测 | 未测 |
| sudohard | 14.868 | 14.444 | 8.478 | 21.972 | 8.914 |
| 高精度1万阶乘 | 0.356 | 不支持 | 0.536 | 不支持 | 不支持 |