所有版本均在linux amd64上运行。有windows版本的则用windows版本测试。各自都执行2次。
基准采用sqlite3.54
https://sqlite.org/2026/sqlite-tools-win-x64-3540100.zip
sql
WITH RECURSIVE
input(sud) AS (
VALUES('....754..........8.8.19....3....1.6........34....6817.2.4...6.39......2.53.2.....'),
('3.........5.7.3..8....28.7.7......43...........39.41.54..3..8..1...4....968...2..')
),
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, instr(sud, '.') FROM input
UNION ALL
SELECT
substr(s, 1, ind-1) || z || substr(s, ind+1),
instr( 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;
C:\d>sqlite35401
SQLite version 3.54.1 2026-10-16 14:45:20
Enter ".help" for usage hints.
Connected to a transient in-memory database.
Use ".open FILENAME" to reopen on a persistent database.
SQLite-3.54 memory-> .timer on
SQLite-3.54 memory-> .read sudomid3.sql
╭─────────────────────────────────────────────────────────────────────────────────────╮
│ s │
╞═════════════════════════════════════════════════════════════════════════════════════╡
│ '693875412145632798782194356357421869816957234429368175274519683968743521531286947' │
│ '387419526259763418641528379716285943594631782823974165472396851135842697968157234' │
╰─────────────────────────────────────────────────────────────────────────────────────╯
Run Time: real 1.201766 user 1.156250 sys 0.031250
SQLite-3.54 memory-> .read sudomid3.sql
╭─────────────────────────────────────────────────────────────────────────────────────╮
│ s │
╞═════════════════════════════════════════════════════════════════════════════════════╡
│ '693875412145632798782194356357421869816957234429368175274519683968743521531286947' │
│ '387419526259763418641528379716285943594631782823974165472396851135842697968157234' │
╰─────────────────────────────────────────────────────────────────────────────────────╯
Run Time: real 1.143157 user 1.125000 sys 0.015625
duckdb分别采用main分支和2.0分支最新每日build。sql改了整除运算符。
sql
WITH RECURSIVE
input(sud) AS (
VALUES('....754..........8.8.19....3....1.6........34....6817.2.4...6.39......2.53.2.....'),
('3.........5.7.3..8....28.7.7......43...........39.41.54..3..8..1...4....968...2..')
),
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, instr(sud, '.') FROM input
UNION ALL
SELECT
substr(s, 1, ind-1) || z || substr(s, ind+1),
instr( substr(s, 1, ind-1) || z || substr(s, ind+1), '.' )
FROM x, digits AS d
WHERE ind>0
AND NOT EXISTS (
SELECT 1
FROM digits AS lp
WHERE d.z = substr(s, ((ind-1)//9)*9 + lp, 1)
OR d.z = substr(s, ((ind-1)%9) + (lp-1)*9 + 1, 1)
OR d.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;
https://artifacts.duckdb.org/latest/duckdb-cli-windows-amd64.tar.gz
C:\d>duckdb1017a
DuckDB v2.1.0-alpha48729 (Unknown Version)
Enter ".help" for usage hints.
memory D .timer on
memory D .read sudomid3duck.sql
┌───────────────────────────────────────────────────────────────────────────────────┐
│ s │
│ varchar │
├───────────────────────────────────────────────────────────────────────────────────┤
│ 693875412145632798782194356357421869816957234429368175274519683968743521531286947 │
│ 387419526259763418641528379716285943594631782823974165472396851135842697968157234 │
└───────────────────────────────────────────────────────────────────────────────────┘
Run Time (s): real 1.202 user 1.171875 sys 0.140625
memory D .read sudomid3duck.sql
┌───────────────────────────────────────────────────────────────────────────────────┐
│ s │
│ varchar │
├───────────────────────────────────────────────────────────────────────────────────┤
│ 693875412145632798782194356357421869816957234429368175274519683968743521531286947 │
│ 387419526259763418641528379716285943594631782823974165472396851135842697968157234 │
└───────────────────────────────────────────────────────────────────────────────────┘
Run Time (s): real 1.196 user 1.375000 sys 0.218750
https://artifacts.duckdb.org/v2.0-cyanoptera/duckdb-cli-windows-amd64.tar.gz
C:\d>duckdb1017
DuckDB v2.0.0-alpha48730 (Cyanoptera)
Enter ".help" for usage hints.
memory D .timer on
memory D .read sudomid3duck.sql
┌───────────────────────────────────────────────────────────────────────────────────┐
│ s │
│ varchar │
├───────────────────────────────────────────────────────────────────────────────────┤
│ 693875412145632798782194356357421869816957234429368175274519683968743521531286947 │
│ 387419526259763418641528379716285943594631782823974165472396851135842697968157234 │
└───────────────────────────────────────────────────────────────────────────────────┘
Run Time (s): real 1.565 user 1.984375 sys 0.343750
memory D .read sudomid3duck.sql
┌───────────────────────────────────────────────────────────────────────────────────┐
│ s │
│ varchar │
├───────────────────────────────────────────────────────────────────────────────────┤
│ 693875412145632798782194356357421869816957234429368175274519683968743521531286947 │
│ 387419526259763418641528379716285943594631782823974165472396851135842697968157234 │
└───────────────────────────────────────────────────────────────────────────────────┘
Run Time (s): real 1.559 user 1.937500 sys 0.250000
datafusion采用python 3.14的55版本。 sql改写了递归中列别名和与列名同名表别名
pip install datafusion
python
s="""
WITH RECURSIVE
input(sud) AS (
VALUES('....754..........8.8.19....3....1.6........34....6817.2.4...6.39......2.53.2.....'),
('3.........5.7.3..8....28.7.7......43...........39.41.54..3..8..1...4....968...2..')
),
digits(z, lp) AS (
VALUES('1', 1)
UNION ALL SELECT
CAST(lp+1 AS TEXT) as z, lp+1 as lp FROM digits WHERE lp<9
),
x(s, ind) AS (
SELECT sud, instr(sud, '.') FROM input
UNION ALL
SELECT
substr(s, 1, ind-1) || z || substr(s, ind+1),
instr( substr(s, 1, ind-1) || z || substr(s, ind+1), '.' )
FROM x, digits AS d
WHERE ind>0
AND NOT EXISTS (
SELECT 1
FROM digits AS lp
WHERE d.z = substr(s, ((ind-1)/9)*9 + lp, 1)
OR d.z = substr(s, ((ind-1)%9) + (lp-1)*9 + 1, 1)
OR d.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;
"""
import time
from datafusion import SessionContext
ctx = SessionContext()
t=time.time();print(ctx.sql(s));print(time.time()-t)
+-----------------------------------------------------------------------------------+
| s |
+-----------------------------------------------------------------------------------+
| 387419526259763418641528379716285943594631782823974165472396851135842697968157234 |
| 693875412145632798782194356357421869816957234429368175274519683968743521531286947 |
+-----------------------------------------------------------------------------------+
7.106393575668335
clickhouse采用每日的最新build。sql改写了递归中列别名, 不同于CTE列名,并改写和与列名同名表别名
https://builds.clickhouse.com/master/amd64/clickhouse
sql
WITH RECURSIVE
input(sud) AS (
VALUES ('....754..........8.8.19....3....1.6........34....6817.2.4...6.39......2.53.2.....'),
('3.........5.7.3..8....28.7.7......43...........39.41.54..3..8..1...4....968...2..')
),
digits(z, lp) AS (
SELECT '1', 1
UNION ALL SELECT
CAST(lp+1 AS TEXT) as z2, lp+1 as lp2 FROM digits WHERE lp<9
),
x(s, ind) AS (
SELECT sud, instr(sud, '.') FROM input
UNION ALL
SELECT
substr(s, 1, ind-1) || z || substr(s, ind+1),
instr( substr(s, 1, ind-1) || z || substr(s, ind+1), '.' )
FROM x, digits AS d
WHERE ind>0
AND NOT EXISTS (
SELECT 1
FROM digits AS lp
WHERE d.z = substr(s, intDiv((ind-1), 9)*9 + lp, 1)
OR d.z = substr(s, ((ind-1)%9) + (lp-1)*9 + 1, 1)
OR d.z = substr(s, (intDiv((ind-1), 3) % 3) * 3
+ intDiv((ind-1), 27) * 27 + lp
+ intDiv((lp-1) , 3) * 6, 1)
)
)
SELECT s FROM x WHERE ind=0;
root@DESKTOP-59T6U68:/mnt/c/d# ./clickhouse2610
ClickHouse local version 26.10.1.1278 (official build).
:) \i sudomid3ch.sql
┌─s─────────────────────────────────────────────────────────────────────────────────┐
1. │ 387419526259763418641528379716285943594631782823974165472396851135842697968157234 │
2. │ 693875412145632798782194356357421869816957234429368175274519683968743521531286947 │
└───────────────────────────────────────────────────────────────────────────────────┘
2 rows in set. Elapsed: 2.291 sec. Processed 1.61 million rows, 171.54 MB (703.99 thousand rows/s., 74.89 MB/s.)
Peak memory usage: 241.46 MiB.
┌─s─────────────────────────────────────────────────────────────────────────────────┐
1. │ 387419526259763418641528379716285943594631782823974165472396851135842697968157234 │
2. │ 693875412145632798782194356357421869816957234429368175274519683968743521531286947 │
└───────────────────────────────────────────────────────────────────────────────────┘
2 rows in set. Elapsed: 2.217 sec. Processed 1.61 million rows, 171.54 MB (727.18 thousand rows/s., 77.35 MB/s.)
Peak memory usage: 250.53 MiB.
cedardb采用current的最新build。沿用sqlite3的sql。
https://download.cedardb.com/latest/cedar-current-amd64.tar.xz
root@6ae32a5ffcde:/par# ./cedardb2609 -i --inmemory
2026-10-15 14:08:14.514450546 UTC INFO: Using 4480 MB buffers, 4480 MB work memory
2026-10-15 14:08:14.531352816 UTC NOTICE: using a transient in-memory database
2026-10-15 14:08:14.531392342 UTC LOG: CEDAR_PASSWORD environment variable missing. Generated initial password for super user 'postgres': jj9FzhxIXSeXud08E20cWc5k3
2026-10-15 14:08:14.571335638 UTC INFO: Using 4973 MB swap space
2026-10-15 14:08:14.939805194 UTC INFO: You're running CEDARDB COMMUNITY EDITION - using 0 GB out of 64 GB. Our General Terms and Conditions apply to the use of the CedarDB Community Edition. Run "cedardb --license" for more information.
> 2026-10-15 14:08:16.028031138 UTC WARNING: Your CedarDB version (v2026-09-16) is out of date!
Please upgrade to the newest version (v2026-10-08) at https://cedardb.com/docs/releases
> \timing on
> \i sudomid3.sql
s
387419526259763418641528379716285943594631782823974165472396851135842697968157234
693875412145632798782194356357421869816957234429368175274519683968743521531286947
2026-10-15 14:09:03.546353972 UTC INFO: [s] execution: (0.056703 min, 0.056703 max, 0.056703 median, 0.056703 avg, 0.000000 sdev, 5 scale, nan IPC, nan CPUs, nan GHz)
> \i sudomid3.sql
s
693875412145632798782194356357421869816957234429368175274519683968743521531286947
387419526259763418641528379716285943594631782823974165472396851135842697968157234
2026-10-15 14:11:05.438749990 UTC INFO: [s] execution: (0.042042 min, 0.042042 max, 0.042042 median, 0.042042 avg, 0.000000 sdev, 5 scale, nan IPC, nan CPUs, nan GHz)
tableauhyperapi采用python最新whl版本
pip download tableauhyperapi
sql采用datafusion改后版本,再把instr(s, '.')改为position('.'in s)
python
s=""""
WITH RECURSIVE
input(sud) AS (
VALUES('....754..........8.8.19....3....1.6........34....6817.2.4...6.39......2.53.2.....'),
('3.........5.7.3..8....28.7.7......43...........39.41.54..3..8..1...4....968...2..')
),
digits(z, lp) AS (
VALUES('1', 1)
UNION ALL SELECT
CAST(lp+1 AS TEXT) as z, lp+1 as lp 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 d
WHERE ind>0
AND NOT EXISTS (
SELECT 1
FROM digits AS lp
WHERE d.z = substr(s, ((ind-1)/9)*9 + lp, 1)
OR d.z = substr(s, ((ind-1)%9) + (lp-1)*9 + 1, 1)
OR d.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;
"""
from tableauhyperapi import HyperProcess, Telemetry, Connection
hyper=HyperProcess(telemetry=None)
con=Connection(endpoint=hyper.endpoint)
>>> import time
>>> con.close()
>>> con=Connection(endpoint=hyper.endpoint)
>>> t=time.time();a=con.execute_list_query(s);print(a);print(time.time()-t)
[['387419526259763418641528379716285943594631782823974165472396851135842697968157234'], ['693875412145632798782194356357421869816957234429368175274519683968743521531286947']]
0.2955057621002197
>>> t=time.time();a=con.execute_list_query(s);print(a);print(time.time()-t)
[['387419526259763418641528379716285943594631782823974165472396851135842697968157234'], ['693875412145632798782194356357421869816957234429368175274519683968743521531286947']]
0.2929530143737793