上个月我拿到一台华为擎云的机器装的是麒麟 V10gfb-2207任务很简单在这台机器上搭好近期的数据分析环境直接把一批几千万行的销售明细查起来给业务出一份月度报表。当时我第一个想到的不是装 MySQL 或者 PostgreSQL而是 DuckDB。原因很直接这只是单机分析场景不需要常驻服务我不想在国产化系统上去折腾一整套数据库服务端用 Python 跑 Pandas 处理千万级数据又慢又吃内存换成 DuckDB 之后一条 SQL 就能把筛选、聚合、排序全干完体感快很多。但真正动手之后发现在麒麟上装 DuckDB 和插件比在普通 CentOS 或者 Ubuntu 上多绕了几道弯中间踩了不少坑也攒下了一套可以复用的完整流程。这篇内容就用我实际操作的顺序来写从环境体检、安装路线、插件加载到最后的日常使用验证每一步都记录清楚“为什么这么做”以及“我踩过哪些不该踩的坑”。如果你是运维、数据分析或者信创项目里的开发拿到一台麒麟 V10 之后想用 DuckDB 干活这篇可以直接照着参考。1. 为什么盯上DuckDB麒麟环境里的嵌入式分析选型1.1 在麒麟服务器上做数据分析会遇到什么麒麟 V10 本身是面向政企和信创场景的 Linux 发行版稳定性没问题但默认软件仓库里可用的“现代数据工具”确实不多。你在 CentOS 上yum install postgresql-server装个数据库很轻松在麒麟上虽然也能用dnf或yum装到但装完之后还要考虑开机自启、用户授权、数据目录、端口防火墙实际维护成本不低。真正的麻烦在于这类机器上通常没有你要的开箱即用分析工具比如 Superset、ClickHouse、Spark 之类如果只为了跑一个报表任务这套重流程完全没必要。我一开始也在犹豫是不是装个 PostgreSQL 就够了。但后来想清楚一个关键点数据文件就是一堆 CSV 和 Parquet放在共享存储上谁拿到这台机器谁分析数据量级大概在几 GB 到几十 GB分析需求偏“聚合查询”而不是“高并发事务”。这种情况下DuckDB 这类嵌入式 OLAP 引擎反而更匹配。它不需要守护进程不需要用户密码不用开端口文件落在哪就把数据库建在哪非常适合“服务器上做本地分析”这种场景。1.2 DuckDB 到底解决了什么核心问题DuckDB 是一款嵌入式列式数据库管理系统底层用了向量化执行引擎专为分析型负载设计。你可以把它理解成“SQLite 的分析版”——同样是零配置文件、单文件存储、嵌入式链接但 SQLite 偏向事务性 OLTP 小数据量DuckDB 则是为几 GB 到几十 GB 的数据聚合、JOIN、窗口函数优化。它支持标准 SQLCTE、多表 JOIN、窗口函数、复杂的聚合表达式都跑得动还直接把读取 CSV、JSON、Parquet 本地文件的能力做进了内核不需要先导入数据再查询。在麒麟这种“要啥没啥”的环境里DuckDB 还有一个很现实的优势安装包极小CLI 方式甚至解压就能用不依赖一堆系统库。后续如果你要做 ETL 或者数据分析还能通过 Python 调用它几个 GB 的数据做 group by 比 Pandas 内存操作舒服得多。所以我把它的定位归纳成三段话事务并发交给正式数据库分析报表这类读多写少的活交给 DuckDB数据文件直接放本地不需要导入导出DuckDB 自己当查询引擎嵌入式特性让它天然适合在国产化服务器、离线环境、内网受限环境里当“分析计算节点”。想清楚这几点之后后面的安装过程就只是工程问题不再需要纠结选型。2. 开局先体检架构、系统版本、Python与GCC的三重确认任何安装步骤在麒麟上跑之前都得先明确三件事系统是什么架构、自带 Python 是什么版本、GCC 编译器能不能编 C17。这三个因素决定你走哪条安装路线。2.1 怎么看系统架构和版本先执行下面这几条命令把所有环境信息一次性摸清uname -m cat /etc/os-release nproc free -h df -h /home我在华为擎云上拿到的结果是这样aarch64 PRETTY_NAMEKylin Linux Advanced Server release V10 (gfb-2207)gfb-2207这个编号代表的是 2022 年 7 月发布的一个构建版本内核是 4.19.x整体偏稳健保守。这里最关键的信息是aarch64也就是 ARM64 架构。DuckDB 官方发布页面早期的 CLI 二进制大多只提供 x86_64也就是linux-amd64但较新版本已经提供了linux-aarch64包所以这条路是通的。只是平台相关的东西比如插件扩展文件、Python 轮子都要认准 aarch64别拿 x86_64 的文件硬试。2.2 自带的 Python 版本有多老麒麟 V10 默认的 Python 版本通常不高我在这台机器上看到的是 Python 3.7.5而 DuckDB 新版 Python 客户端对 Python 版本有要求较新的 wheel 往往需要 Python 3.8 甚至更高。这就是为什么你在搜索这个问题时会看到大量“在 kylin v10-gfb-2207 上手动升级 python”的帖子——不是大家闲着没事升级而是新工具链真的需要。还有一个很隐蔽的坑麒麟系统的系统组件深度依赖/usr/bin/python3比如说包管理器或者系统服务脚本可能会调用它。所以千万不要把系统自带的 Python 直接删掉或者替换掉那样很可能会把系统的包管理弄挂。正确做法是另装一个 Python软链到/usr/local/bin/python3.11这类独立路径然后配好 PATH让python3默认指向新版本即可系统自带的保留不动。2.3 为什么有人说要“编译 gcc 12”DuckDB 从源码编译时对编译器的要求是支持 C17理想情况下推荐 GCC 10 以上。麒麟 V10 自带的 GCC 版本一般是 4.8.5 或者 7.3.14.8.5 根本不会完整支持 C177.3.1 能编一部分但容易在模板展开阶段出现莫名其妙的“内部编译器错误”。这就是网上有人折腾“kylin v10 编译 gcc 12”的原因——要给 DuckDB 源码编译准备一套像样的工具链。如果你只是下载编译好的二进制完全可以不管 GCC。但如果你要走源码编译或者要自己编译 DuckDB 的社区插件那么 GCC 版本检查这一步绕不开。检查命令很简单gcc --version我在那台机器上看到的 GCC 是 7.3.1所以我当时就决定先升级一套独立的 GCC 12再处理 DuckDB 源码编译。升级 GCC 这件事本身也要避开系统默认路径最好安装到/usr/local/gcc-12然后用CC和CXX环境变量指定编译器不要动/usr/bin/gcc的默认链接避免系统其他软件发生 ABI 兼容问题。3. 三条安装路线实测与踩坑记录在麒麟系统上装 DuckDB目前其实有三条可走的路线下载官方 CLI 二进制、用 pip 安装 Python 包、从源码编译。三条路我都实际跑过各自有各自的坑下面分开讲。3.1 最快线路官方CLI二进制直接解压即用如果你只需要在命令行里跑 SQL 分析不需要在 Python 里调用那最省事的方案就是下载官方静态编译的 CLI。DuckDB 的 GitHub Releases 页面里每个版本都会提供多种平台打包文件找文件名类似duckdb_cli-linux-aarch64.zip的那个下载就行。在联网环境下可以这样cd /opt wget https://github.com/duckdb/duckdb/releases/download/v1.1.3/duckdb_cli-linux-aarch64.zip unzip duckdb_cli-linux-aarch64.zip chmod x duckdb mv duckdb /usr/local/bin/注意需要联网访问外网时可能有下载慢的问题我建议在有公网环境的机器上先下载好文件再用内网工具传到目标机器上。下载完成后验证版本duckdb --version这个方式的最大优点是快而且静态编译的 CLI 不依赖系统上的 libstdc、libgcc基本解压就能跑。我实际测过在麒麟 V10 aarch64 上运行SELECT version();完全正常。但也别高兴太早官方 CLI 虽然自带了一部分核心扩展比如 parquet、json、fts很多社区扩展比如 sqlite_scanner、postgres_scanner、vss 并不在 CLI 内需要后续单独安装。这就引出了本文后面的插件问题。3.2 Python路线pip安装和“升级Python”的真实原因如果我需要在 Python 脚本里跑 SQL或者要把查询结果直接转 Pandas DataFrame那就得走 pip 安装。这里面最大的痛点就是 Python 版本匹配。以 DuckDB 1.1.3 为例PyPI 上只提供支持 Python 3.9 的 wheel。因此你如果还在用系统自带的 Python 3.7.5直接执行pip install duckdb通常会报找不到匹配的 wheel或者只能降级装一个非常老的版本比如 0.6.x而老版本缺少很多新特性。网上那些“手动升级 Python”的教程本质上就是要解决这个 wheel 匹配问题。我当时的操作是编译安装了一个 Python 3.11.8 到/usr/local/python3.11步骤要点如下yum install -y wget make gcc openssl-devel bzip2-devel libffi-devel readline-devel sqlite-devel wget https://www.python.org/ftp/python/3.11.8/Python-3.11.8.tgz tar xzf Python-3.11.8.tgz cd Python-3.11.8 ./configure --prefix/usr/local/python3.11 --enable-optimizations make -j$(nproc) make install装完后把新 Python 的路径加进 PATH并升级 pipexport PATH/usr/local/python3.11/bin:$PATH python3 -m pip install --upgrade pip然后就可以正常安装 DuckDBpython3 -m pip install duckdb python3 -c import duckdb; print(duckdb.__version__)这里有个很重要的经验不要把新 Python 直接做成/usr/bin/python3的软链接因为麒麟的桌面组件和系统脚本可能会调用/usr/bin/python3如果版本突然变了很容易出现系统组件起不来的问题。我自己的习惯是建/usr/local/bin/python3.11软链然后在用户级~/.bashrc里配 PATH这样只有交互式终端生效系统服务不受影响。3.3 兜底路线源码编译以及gcc升级的完整过程源码编译在三条路线里最麻烦但也是扩展能力最强、最“可控”的一条。之前的坑集中在系统自带 GCC 版本太老。我实测用 GCC 7.3.1 编译 DuckDB 源码在模板实例化阶段会直接报internal compiler error。所以如果你要源码编译第一步一定是先把 GCC 升级到 10 以上我用的版本是 GCC 12.2。升级 GCC 我这里不展开讲几百行编译脚本只把关键步骤列出来wget https://ftp.gnu.org/gnu/gcc/gcc-12.2.0/gcc-12.2.0.tar.xz tar xJf gcc-12.2.0.tar.xz cd gcc-12.2.0 ./contrib/download_prerequisites mkdir build cd build ../configure --prefix/usr/local/gcc-12 --enable-languagesc,c --disable-multilib make -j$(nproc) make install装完后要把新 GCC 加进 PATH并设置编译器环境变量确保后续编译使用新版本export PATH/usr/local/gcc-12/bin:$PATH export CC/usr/local/gcc-12/bin/gcc export CXX/usr/local/gcc-12/bin/g接下来下载 DuckDB 源码编译git clone https://github.com/duckdb/duckdb.git cd duckdb git checkout v1.1.3 make -j$(nproc)编译过程在 ARM 架构上会持续一段时间我大概等了十几分钟。如果make后生成了build/release/duckdb说明编译成功。这一步最关键的一点就是开头那组环境变量很多人在麒麟上编译失败原因就是 make 没有跟上新 GCC仍然用了/usr/bin/g老版本。3.4 三条路线怎么选一张表理清适用场景不同使用方式对应不同安装路线我把判断逻辑整理成下表使用场景推荐路线理由命令行跑 SQL、CSV/Parquet 分析官方 CLI 二进制最快依赖最少Python 数据分析、ETLpip 安装 Python 包与 Pandas/Jupyter 配合最好需要自己编译或验证最新代码源码编译扩展最灵活但耗时最多内网离线环境官方 CLI 二进制 离线 wheel避免复杂构建依赖我实际工作中是“官方 CLI Python 包”双装的两者版本保持一致。CLI 处理临时查询Python 包跑正式 ETL互不干扰。源码编译那条路更多是为了之后编译社区插件做准备属于“兜底中的兜底”。4. 插件安装核心扩展与社区扩展的两种情况标题里写了“和插件”这部分其实是麒麟环境下最难处理的地方因为插件安装涉及平台标识、网络仓库、动态库编译三件麻烦事。4.1 先分清插件类型内置扩展、核心扩展和社区扩展DuckDB 的“插件”在官方术语里叫 Extension扩展粗分三类内置扩展编译在 DuckDB 主体里不需要单独安装比如json、parquet、excel、fsst、fts等在 v1.x 里默认可用核心扩展官方维护建议默认启用但需要INSTALL和LOAD才能用比如httpfs、sqlite_scanner、postgres_scanner社区扩展由第三方维护需要从社区扩展仓库下载比如arrow、vss、motherduck等。在麒麟系统上最容易出问题的就是后两类因为它们要在运行时下载动态库文件。DuckDB 的扩展机制是你执行INSTALL sqlite;之后它会根据当前 DuckDB 版本和操作系统平台拼出一个下载地址然后下载对应的.duckdb_extension文件到本地扩展目录后续LOAD sqlite;再把它加载进来。问题来了DuckDB 官方扩展仓库基本覆盖了主流的linux_amd64和osx_arm64平台但对于linux_arm64这类组合支持往往不全或者说某些核心扩展有某些社区扩展没有。4.2 让INSTALL/LOAD在麒麟上顺畅工作的关键我第一次在这台麒麟机器上执行INSTALL sqlite;的时候报错信息大致是Error: could not locate a matching extension for sqlite这个报错不是 DuckDB 坏了而是官方扩展源里没有提供与当前 DuckDB 版本和平台匹配的扩展文件。遇到这种情况第一个要查的是 DuckDB 版本对应的平台字符串。可以在 CLI 里这样看SELECT extension_name, platform, installed FROM duckdb_extensions();这个查询会把所有可用扩展的下载平台列出来。我在麒麟上看到的是linux_arm64_gcc4这类平台名这就说明如果你去官方扩展仓库里找linux_arm64_gcc4目录下的文件大概率能找到一部分扩展。要在受限网络环境下安装核心扩展我建议采用“中转机下载 手动放置”的方式在另一台能访问外网的 Linux x86 机器上也装一个同版本 DuckDB先执行INSTALL xxx;让它生成扩展文件找到扩展文件位置~/.duckdb/extensions/version/platform/如果 x86 的扩展文件在 ARM 上不能用那就必须到 DuckDB 的扩展下载地址里手动下载linux_arm64_gcc4平台的对应文件把下载好的.duckdb_extension文件传到麒麟机器的扩展目录通常也是~/.duckdb/extensions/version/platform/进入 DuckDB 执行LOAD sqlite;确认加载成功。为了验证扩展文件是否匹配可以执行duckdb -c LOAD sqlite; SELECT 1;如果不再报错就说明插件已经生效。4.3 手动放置插件文件的具体操作手动放文件是“最土但最有效”的方法尤其适合防火墙严格的内网机器。我当时用这种方式安装sqlite_scanner不到十分钟就搞定了。具体路径可以分两步确认先看扩展仓库地址再看平台目录。SELECT * FROM duckdb_settings() WHERE name LIKE %extension%;这个查询会显示类似extension_directory和autoinstall_known_extensions之类的配置项。DuckDB 默认扩展目录是~/.duckdb/extensions/version/platform/。如果你想换成项目目录可以设置SET extension_directory/data/duckdb/extensions;之所以推荐手动设置扩展目录是因为当你在不同机器之间迁移项目时扩展文件也可以一起拷贝不用重新下载。下面是我手动放置sqlite_scanner时的示例mkdir -p /data/duckdb/extensions/v1.1.3/linux_arm64_gcc4 cp sqlite_scanner.duckdb_extension /data/duckdb/extensions/v1.1.3/linux_arm64_gcc4/ duckdb -c SET extension_directory/data/duckdb/extensions; LOAD sqlite; SELECT 1;注意扩展文件的名称和 DuckDB 模块名必须严格一致文件名不能随便改。如果文件名不对LOAD 的时候会直接报“Cant open the module file”。还有一个细节在较新版本的 DuckDB 里扩展仓库地址可能指向 GitHub 或 Hugging Face 上的官方仓库现场环境访问不了是很正常的。这不代表插件装不了只是需要换一种“离线”思路。我常用的两个离线来源一是官方 Releases 页面里附带的部分扩展包二是在能联网的同版本机器上安装后把整个扩展目录打包拷过去。如果你的需求是社区扩展比如arrow、httpfs的某些新特性且官方仓库里没有现成的 aarch64 文件那只能自己编译扩展。命令大致如下cd duckdb GENninja make sqlite_scanner前提是第三步里的 GCC 12 工具链已经就绪。编译生成的扩展文件会出现在build/release/extension目录下把它拷到扩展目录就能用。这个过程我走通过但只建议确实没有离线文件时才用——因为编译时间比较长而且不同版本之间的兼容性容易出幺蛾子。5. 验证与日常使用别装完就扔一边安装和插件只是第一步真正验证“能不能干活”的环节是用真实查询去压一把。这个环节我踩过的坑最典型也最容易在初次上手时被忽略。5.1 用一套线上查询验证安装装好之后我建议先创建一张测试表导入一条 CSV 数据跑一个带聚合的 SQL确认整个链路没问题。我的做法是直接用 DuckDB 内置的 range 函数造一千万行数据CREATE TABLE test AS SELECT i % 1000 AS grp, random() AS val FROM range(10000000); SELECT grp, sum(val), avg(val), count(*) FROM test GROUP BY grp ORDER BY grp LIMIT 10;如果在 CLI 下执行顺畅说明 CPU、内存、模拟器指令集这些基本的能正常工作。实际在麒麟 V10 aarch64 上一千万行 group by 大概只花了零点几秒这个体感比 Pandas 好太多。接着测一下真实文件读取能力。我用一台机器上已有的 CSV大约 2.5 GB直接用 DuckDB 查SELECT count(*), sum(amount) FROM read_csv_auto(/data/sales_2024.csv);read_csv_auto会自动推断表结构不需要预先建表相当省事。我在第一次跑的时候遇到的问题其实是字符编码麒麟系统默认的LANG可能是en_US.UTF-8但 CSV 是 GBK 编码导致中文字段乱码。解决办法是在read_csv_auto里指定编码参数ENCODINGGB18030或者在启动 DuckDB 之前先export LANGzh_CN.UTF-8。5.2 与pandas互转的实操笔记如果我的 Python 环境安装成功这一步在麒麟上非常有价值。因为很多同事的业务数据最终要落到 Excel 或者报表工具里用 DuckDB 直接在 Python 里做转换比传统 Pandas 节省内存。示例代码如下import duckdb con duckdb.connect(/data/report.duckdb) df con.execute( SELECT region, sum(amount) AS total FROM read_csv_auto(/data/sales_2024.csv) GROUP BY region ).df() print(df.head())运行这段代码时要注意如果/usr/bin/python3还是系统旧版本而你用python3启动脚本可能会导入不到新装的 duckdb。建议在脚本第一行注释里写明要用/usr/local/python3.11/bin/python3运行或者在.bashrc里把 PATH 配到最前面。另外DuckDB 与 pandas 互转时有一个容易掉进去的“时间类型”坑麒麟系统自带的 pandas 如果版本特别旧可能不支持某些新的时间类型导致df()转换报错。解决方法是升级 pandas 到 2.x/usr/local/python3.11/bin/python3 -m pip install -U pandas我在实测中发现pandas 2.0 之后对 Arrow 后端支持更好DuckDB 查询结果转 DataFrame 的速度明显提升。5.3 日常维护时容易忽略的几个点最后说几个日常使用中容易踩的细节都是我实际碰到过的。第一~/.duckdb的磁盘空间。DuckDB 下载的扩展文件就存在这下面如果你的 home 目录空间比较小多装几个扩展之后可能把~塞满。尤其是数据量大的时候数据库文件、临时文件也会膨胀。建议在比较靠前的位置尽早把扩展目录迁到数据盘我前面提到的SET extension_directory/data/duckdb/extensions就是这个用意。第二系统自带的 Python 版本很老如果你不想为了 DuckDB 单独升级 Python又想用 pip 安装那就老老实实装一个与旧 Python 兼容的旧版 DuckDB比如pip install duckdb0.8.1。但我个人不推荐这条“将就”路线新版在 SQL 解析和列式存储上优化了很多尤其面对几千万行的数据新版本性能差距明显还是升级 Python 更稳妥。第三在同一台机器上如果你同时装了多个 DuckDB 版本不同版本的扩展仓库目录是隔离的升级 DuckDB 后别忘了重新INSTALL或者迁移扩展文件。经常有人升级完 DuckDB执行查询时发现某个LOAD失败就是因为扩展目录里还是旧版本的文件。第四关于文件和目录权限。麒麟系统的/data目录可能在创建时没有给普通用户写权限而 DuckDB 在创建数据库文件时如果权限不够会报类似Permission denied的错误。如果遇到别急着怀疑 DuckDB先ls -ld /data看一眼属主和权限。最后分享一个我个人的小习惯做完环境安装后我会把整个验证流程写成一个check_duckdb.sh脚本里面依次执行版本检查、扩展目录检查、CSV 读取、TPC-H 类简单聚合、Python 导入检查。这样换一台麒麟机器、或者同事接手环境时直接跑一遍脚本就知道环境是否可用不需要重新摸索。这套流程我在好几台华为和飞腾的机器上都验证过整体稳定希望这篇文章能帮你在麒麟上少走几步弯路。