duckdb、clickhouse、datafusion、cedardb、tableauhyperapi 5种分析型数据库执行递归求数独SQL比较

所有版本均在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

https://files.pythonhosted.org/packages/4a/77/647677c9c9f9fcdd351e3a7e5c856f22e6e91dc56a0dcc76246c82017e7b/datafusion-55.0.0-cp310-abi3-win_amd64.whl

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

https://files.pythonhosted.org/packages/81/d5/b4b30d926e23614b8a47c6417d464fde8c8a09b523c3a8cafa641c940496/tableauhyperapi-0.0.26784-py3-none-win_amd64.whl

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
相关推荐
泡海椒1 小时前
JQuick-SQL Worker 生命周期:端口、启动与关闭规范
数据库·sql
麦壳饼1 小时前
SonnetDB:KNN 查询的距离语义与维度边界
数据库·sonnetdb
知行产研2 小时前
三年三起收购,拆解卡特彼勒AI并购版图
数据库·人工智能·mysql
2603_954708312 小时前
微能网协调控制箱突破传统微电网架构瓶颈
大数据·数据库·人工智能·架构·能源
l1t2 小时前
一个clickhouse易错的语法问题
数据库·sql·clickhouse
啵啵啵鱼2 小时前
六、联合查询
数据库·oracle
蓝胖的四次元口袋2 小时前
Redis 知识梳理(4)
数据库·redis
foolishlee2 小时前
Neon compute GetPage
数据库