ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

pgloader LOAD ARCHIVE 命令深度实战:从 ZIP 归档与 HTTP 链接加载 CSV / DBF / FIXED 数据到 PostgreSQL

pgloader LOAD ARCHIVE 命令深度实战:从 ZIP 归档与 HTTP 链接加载 CSV / DBF / FIXED 数据到 PostgreSQL 数据工程ETL数据集成数据库【免费下载链接】pgloaderMigrate to PostgreSQL in a single command!项目地址https://gitcode.com/gh_mirrors/pg/pgloader点击查看免费下载本文是 pgloader 中LOAD ARCHIVE命令的完整技术指南。该命令允许一条命令同时完成「下载归档 → 解压 → 匹配归档内的数据文件 → 加载进 PostgreSQL」目前官方文档承诺的归档格式为 ZIP且归档可以直接来自 HTTP URL。读完本文你将掌握LOAD ARCHIVE的完整语法骨架、FROM归档源规范、FILENAME MATCHING正则匹配子命令、BEFORE LOAD/FINALLY DO钩子并结合仓库源码理解下载、解压与文件匹配的底层实现。本文内容以仓库文档 docs/ref/archive.rst 为主体骨架源码与测试佐证来自 src/utils/archive.lisp、src/parsers/command-archive.lisp 及 test/archive.load 等文件。一、LOAD ARCHIVE能做什么LOAD ARCHIVE让 pgloader 从一个归档文件中加载一个或多个数据文件的内容。官方文档明确说明目前受支持的归档格式是 ZIP且归档可以通过 HTTP URL 下载。它最典型的应用场景是数据源以 ZIP 打包发布且定期更新如 GeoIP 地理库、行政区划编码库数据文件不在本地需要 pgloader 自行从网络抓取一个归档里包含多个同构或异构的数据文件需要一次命令全部入库。从源码结构看src/utils/archive.lisp 中实际定义的支持类型比文档更宽(defparameter *supported-archive-types* (:tar :tgz :gz :zip))也就是说底层实现对tar、tgz、gz、zip四种类型都有展开路径但官方文档承诺并重点讲解的是 ZIP 场景日常使用建议以文档为准。二、命令总体骨架与语法规则LOAD ARCHIVE的命令结构由源码 src/parsers/command-archive.lisp 中的语法规则定义完整骨架如下LOAD ARCHIVE FROM 归档路径或 HTTP URL INTO postgresql 连接 URI -- 可选归档级目标库 BEFORE LOAD DO ... / EXECUTE ... -- 可选加载前 SQL 子命令 1 AND 子命令 2 AND ... FINALLY DO ... -- 可选加载后 SQL其中LOAD ARCHIVE FROM 源是命令起始源码archive-source规则src/parsers/command-archive.lisp子命令之间用AND连接构成archive-command-listBEFORE LOAD与FINALLY均为可选子句。源码中有一个值得注意的硬性约束src/parsers/command-archive.lispWhen using a BEFORE LOAD DO or a FINALLY block, you must provide an archive level target database connection.只要命令里写了BEFORE LOAD DO或FINALLY块就必须同时提供归档级的INTO postgresql://...目标连接否则解析阶段直接报错。原因很直观BEFORE LOAD/FINALLY里的 SQL 要在归档级目标库上执行没有连接无从谈起。三、完整配置示例一条命令加载 GeoLiteCity官方文档给出的示范命令保存在.load命令文件中通过pgloader archive.load执行$ pgloader archive.loadarchive.load的内容如下出自 docs/ref/archive.rst完整的可运行版本位于 test/archive.loadLOAD ARCHIVE FROM /Users/dim/Downloads/GeoLiteCity-latest.zip INTO postgresql:///ip4r BEFORE LOAD DO $$ create extension if not exists ip4r; $$, $$ create schema if not exists geolite; $$, EXECUTE geolite.sql LOAD CSV FROM FILENAME MATCHING ~/GeoLiteCity-Location.csv/ WITH ENCODING iso-8859-1 ( locId, country, region null if blanks, city null if blanks, postalCode null if blanks, latitude, longitude, metroCode null if blanks, areaCode null if blanks ) INTO postgresql:///ip4r?geolite.location ( locid,country,region,city,postalCode, location point using (format nil (~a,~a) longitude latitude), metroCode,areaCode ) WITH skip header 2, fields optionally enclosed by , fields escaped by double-quote, fields terminated by , AND LOAD CSV FROM FILENAME MATCHING ~/GeoLiteCity-Blocks.csv/ WITH ENCODING iso-8859-1 ( startIpNum, endIpNum, locId ) INTO postgresql:///ip4r?geolite.blocks ( iprange ip4r using (ip-range startIpNum endIpNum), locId ) WITH skip header 2, fields optionally enclosed by , fields escaped by double-quote, fields terminated by , FINALLY DO $$ create index blocks_ip4r_idx on geolite.blocks using gist(iprange); $$;这个示例一气呵成地展示了LOAD ARCHIVE的四个核心环节3.1BEFORE LOAD加载前的数据库准备BEFORE LOAD接受两种写法DO子句直接跟一组dollar-quoted以$$包裹的 SQL 语句语句之间用逗号分隔例如创建扩展、建 schemaEXECUTE xxx.sql从 SQL 文件批量读取语句执行实现上支持 PostgreSQL 的 dollar-quoting 以及\i/\ir包含指令与 psql 批处理行为一致。示例中先确保ip4r扩展与geoliteschema 存在再执行geolite.sql完成建表。BEFORE LOAD的通用语义见 docs/command.rst 中Common Clauses一节的说明。3.2 归档级目标库INTO归档级INTO postgresql:///ip4r是BEFORE LOAD/FINALLY中 SQL 的执行目标也是前面提到的硬性约束要求必须提供的连接。3.3 两个 CSV 子命令归档内有两个 CSV 数据文件分别用LOAD CSV ... AND LOAD CSV ...声明Location文件被投影进geolite.location表其中经纬度两列在INTO阶段通过USING表达式(format nil (~a,~a) longitude latitude)动态拼成 PostgreSQL 的point类型输入串Blocks文件把 IP 段的起止整数通过(ip-range startIpNum endIpNum)变换成ip4r扩展的区间类型。这正是 pgloaderUSING投影的典型用法每条USING表达式都是合法的 Common Lisp 形式在pgloader.transforms包环境下读取并在运行时编译为原生代码参见 docs/command.rst 中INTO一节因此可以在加载过程中就地完成数据类型变换而不是事后在数据库里二次加工。3.4FINALLY DO加载完成后的收尾 SQLFINALLY DO中的 SQL 在所有数据子命令都成功导入后执行。示例用它创建 GiST 索引以加速 IP 区间查询——这是把加载与建索引编排进同一条命令的典型做法。四、Archive Source SpecificationFROM 归档源FROM子句指定数据来源可以是本地文件路径直接指向一个 ZIP 文件HTTP/HTTPS URIpgloader 先把文件下载到本地再进入解压流程。下载实现位于 src/utils/archive.lisp 的http-fetch-file使用 Drakma 以二进制流方式请求:force-binary t :want-stream t按 4096 字节缓冲区循环写盘只有 HTTP 状态码为 200 才继续否则记录fatal日志并报错从 URL 推导临时文件名时会先剥离 query string 与 fragment?之后的部分避免文件名被参数污染文件写入$TMPDIR默认临时目录下并返回下载后的路径名。解压逻辑在expand-archivesrc/utils/archive.lispZIP 归档调用系统命令unzip -o 归档 -d 展开目录见 src/utils/archive.lisp展开目录为$TMPDIR下的归档名/子目录$TMPDIR未设置或指向不存在的目录时回退到/tmp解压完成后后续所有子命令都从该顶层目录出发工作。从源码看tar、tgz归档同样通过tar xf展开gz单文件归档则用gunzip -c输出为普通文件。解压前会校验归档文件存在性probe-file不存在直接报错。五、Archive Sub Commands归档子命令5.1 支持哪些子命令官方文档说明目前归档上下文只支持三类数据命令CSV、FIXED、DBF。这与源码规则一致src/parsers/command-archive.lisp(defrule archive-command (or load-csv-file load-dbf-file load-fixed-cols-file))也就是说你可以在一个归档里混合加载 CSV、定宽文本FIXED和 DBF 三类文件命令间用AND串接。5.2FROM FILENAME MATCHING按正则匹配归档内文件子命令的FROM支持FILENAME MATCHING子句让命令不依赖归档目录的具体文件名——只要文件符合正则就命中从而天然兼容目录结构随版本变化的发布包。官方规定的matching子句语法为FROM [ ALL FILENAMES | [ FIRST ] FILENAME ] MATCHINGFROM FILENAME MATCHING ~/regex/匹配第一个命中的文件单个文件加载FROM FIRST FILENAME MATCHING ~/regex/与上者等价FIRST可省略FROM ALL FILENAMES MATCHING ~/regex/匹配所有命中的文件批量加载同名模式的文件。语法解析位于 src/parsers/command-csv.lispfirst-filename-matching与all-filename-matching两条规则分别生成:regex :first/:regex :all标记正则本身用引号包裹。正则匹配的底层实现在 src/utils/archive.lisp 的get-matching-filenames用cl-ppcre的scan对展开目录中的每个文件路径做正则扫描递归遍历fad:walk-directory后返回命中文件列表。此外matching子句还可以追加IN DIRECTORY 路径限定搜索目录src/parsers/command-csv.lisp未指定时默认从当前工作目录搜索。5.3 子命令如何定位归档内的文件这是理解归档加载的关键实现细节LOAD ARCHIVE在执行时会动态绑定全局变量*fd-path-root*为解压目录src/parsers/command-archive.lisp随后所有子命令中的相对文件名都会以该目录为根解析见 src/sources/common/files-and-pathnames.lisp 与 src/sources/csv/csv-database.lisp。所以子命令里只需要写文件名模式pgloader 会自动把它锚定到归档解压后的目录树上。六、Archive Final SQL CommandsFINALLY DOFINALLY DO在所有数据加载完成后执行的 SQL 查询典型用途是CREATE INDEX、加约束、重建触发器等收尾工作。与BEFORE LOAD DO相同FINALLY DO也使用 dollar-quoted、逗号分隔的 SQL 列表。运行统计中该阶段以finally行单独呈现见下节运行输出。顺带一提仓库测试文件 test/archive.load 中的收尾子句写作AFTER LOAD DO $$ create index ... $$;这是同一语义在实际测试中的另一种措辞变体最终效果一致。七、通用子句Common ClausesLOAD ARCHIVE内部各数据命令CSV / DBF / FIXED的WITH、SET、BEFORE/AFTER LOAD DO/EXECUTE、INTO列投影等均继承 pgloader 的通用子句体系详见 docs/command.rstWITH命令级选项如skip header 2、fields terminated by ,、fields optionally enclosed by 、fields escaped by double-quote以及所有数据源通用的on error stop、batch rows R、batch size ... MB、prefetch rows ...等批处理选项SET为 pgloader 打开的每个会话设置 PostgreSQL 会话参数BEFORE LOAD DO/BEFORE LOAD EXECUTE加载前执行 SQL 或 SQL 文件AFTER LOAD DO/AFTER LOAD EXECUTE加载完成后执行 SQL 或 SQL 文件创建索引、约束、重开触发器的最佳时机INTO列投影目标列可以是源字段名也可以是列名 PostgreSQL 类型 USING表达式的组合支持加载时动态变换数据类型。八、实战运行与结果解读以 GeoLiteCity 为例运行pgloader archive.load的完整输出记录在 docs/tutorial/geolite.rst该教程与本文档配套可交叉阅读。关键输出如下... LOG Fetching http://geolite.maxmind.com/.../GeoLiteCity-latest.zip ... LOG Extracting files from archive .../T/pgloader//GeoLiteCity-latest.zip table name read imported errors time ----------------- --------- --------- --------- -------------- download 0 0 0 11.592s extract 0 0 0 1.012s before load 6 6 0 0.019s ----------------- --------- --------- --------- -------------- geolite.location 470387 470387 0 7.743s geolite.blocks 1903155 1903155 0 16.332s ----------------- --------- --------- --------- -------------- finally 1 1 0 31.692s输出里的几个阶段与本文介绍的实现一一对应downloadHTTP 抓取阶段源码中以with-stats-collection (download :section :pre)统计src/parsers/command-archive.lispextract归档解压阶段同样以:pre节统计before loadBEFORE LOAD中的 6 条 SQL两个表两个 CSV 子命令的导入结果finallyFINALLY DO中的建索引语句。加载完成后即可用 ip4r 扩展做 IP 归属查询验证数据质量select * from geolite.location l join geolite.blocks b using(locid) where iprange 8.8.8.8;九、更多真实案例从 HTTP 下载 DBF 归档归档加载不限于 CSV。仓库测试 test/dbf-zip.load 展示了一条LOAD ARCHIVE变体直接LOAD DBF从 HTTPS 下载一个 ZIP 归档解压后加载其中的 DBF 文件并在BEFORE LOAD DO里创建目标 schemaLOAD DBF FROM https://www.insee.fr/fr/statistiques/fichier/2114819/france2016-dbf.zip with encoding cp850 INTO postgresql:///pgloader TARGET TABLE dbf.france2016 WITH truncate, create table BEFORE LOAD DO $$ create schema if not exists dbf; $$;它演示了两个要点归档源可以来自 HTTPSDBF 归档配合WITH ENCODING cp850处理非 UTF-8 的字符集数据。注意单文件加载非LOAD ARCHIVE编排时pgloader 也会自动完成 HTTP 下载与归档展开再按TARGET TABLE建表入库。十、小结与进阶路径LOAD ARCHIVE的核心价值是把「下载、解压、匹配文件、投影变换、加载、建索引」整条链路收敛为一条幂等的命令文件非常适合定期更新的打包数据源GeoIP、行政区划、行业统计年鉴等。继续深入可参考官方参考docs/ref/archive.rst本文档源文件配套教程docs/tutorial/geolite.rst含完整运行输出与查询验证可运行测试test/archive.loadGeoLiteCity 全流程、test/dbf-zip.loadHTTPS 下载 DBF 归档实现源码src/utils/archive.lisp下载/解压/匹配、src/parsers/command-archive.lisp语法规则通用子句docs/command.rstCommon Clauses 完整说明。只要归档内文件命名规律稳定哪怕是子目录嵌套一条LOAD ARCHIVE命令就能全自动地把整个数据包搬进 PostgreSQL这正是 pgloader「Migrate to PostgreSQL in a single command!」理念在文件型数据源上的集中体现。赞分享数据工程ETL数据集成数据库【免费下载链接】pgloaderMigrate to PostgreSQL in a single command!项目地址https://gitcode.com/gh_mirrors/pg/pgloader点击查看免费下载相关推荐pgloader 组合实战LOAD ARCHIVE LOAD FIXED 加载美国人口普查固定宽度文本census-places 测试全解析pgloader 组合实战LOAD ARCHIVE LOAD FIXED 加载美国人口普查固定宽度文本census places 测试全解析 导读 本数据工程ETL数据集成数据库华为TCX转换器3步解决运动数据跨平台同步难题华为TCX转换器3步解决运动数据跨平台同步难题 你是否为华为手表记录的跑步数据无法在Strava、Garmin等主流平台分享而烦恼华为TCX转换器正是为解决数据工程ETL数据集成数据库Johnny-Five 使用 CD74HC4067 16 通道模拟输入扩展板Arduino Nano Backpack实战指南Johnny Five 使用 CD74HC4067 16 通道模拟输入扩展板Arduino Nano Backpack实战指南 导读 本文基于 Johnny数据工程ETL数据集成数据库上一篇Umi-OCR终极指南3分钟掌握免费开源离线OCR的完整应用方案下一篇Python程序分发革命告别命令行Auto PY to EXE让打包变得如此简单创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进