DeepSeek总结的数据库外部表
来源:https://motherduck.com/blog/internal-vs-external-storage-whats-the-limit-of-external-tables/
本文系统回顾了外部表(External Tables)25年来的发展历程、核心价值、适用场景及现代演进,并给出了使用建议。
外部表的核心概念与历史
外部表是一种不存储在数据库内部、而是指向外部数据(如CSV、Parquet、JSON等文件)的表结构。用户通过DDL定义其结构后,即可像查询普通表一样用SQL直接查询外部数据,实现“数据原地访问,无需迁移”。最早可追溯到1992年Microsoft Access的链接表,2001年Oracle 9i正式引入外部表,随后被IBM、SQL Server、Hive、Snowflake、BigQuery等广泛采用。其持久生命力源于“数据在哪里读哪里,比移动它更高效”的基本原则。
工作原理与类比
外部表本质上是一个“指针”或“符号链接”,指向外部存储(如文件系统、S3、GCS)。执行查询时,数据库通过访问驱动(如Oracle的ORACLE_LOADER)读取外部文件并解析成表格形式。删除外部表仅删除元数据,不影响原始数据。它与临时表的区别在于:临时表是会话级、可写、快速但短暂;外部表是持久元数据、只读、无限容量、成本优化。
内部存储 vs. 外部表:关键权衡
| 维度 | 内部存储 | 外部表 |
|---|---|---|
| 数据温度 | 热数据(频繁查询) | 冷数据(归档、偶尔查询) |
| 典型场景 | 仪表板、低延迟查询 | 数据湖增强、一次性分析 |
| 查询速度 | 快(毫秒级) | 慢1.3~1.7倍(但对冷数据可接受) |
| 存储成本 | 较高(如Snowflake ~$23/TB/月) | 极低(S3 Glacier Deep Archive ~$1/TB/月) |
| 数据新鲜度 | 依赖ETL刷新,可能滞后 | 始终最新,无需刷新 |
| 运维负担 | 可预测,由仓库管理 | 小文件问题、影响上游源系统 |
结论:高频、低延迟的“热”数据放在内部;低频、归档、探索性的“冷”数据用外部表,成本优势巨大。
现代演进:从CSV到湖仓一体
外部表已从最初只能读CSV,演进到支持Parquet、Avro、ORC等列式格式,并融入开放表格式(如Iceberg、Delta Lake、Hudi)。这些格式提供ACID事务、时间旅行、模式演进等数据库特性,使外部表成为湖仓架构的基石。DuckDB等新引擎甚至无需显式创建外部表,通过read_parquet()、ATTACH等语法即可实现“零拷贝”外部查询。
此外,开放数据目录(如INFORMATION_SCHEMA)和ADBC(列式API,替代传统ODBC)进一步降低了外部数据的连接和访问成本。
性能基准与关键发现
作者基于TPC-H SF=1数据(600万行)进行测试:
- 内部DuckDB:中位数23.8ms
- 外部Parquet / DuckLake / Iceberg:4156ms(1.31.7倍开销)
- 冷数据场景(每周查询一次):差异可忽略
- 存储压缩:Parquet比DuckDB原生格式小40%
- 元数据开销:Iceberg在50次单行插入时产生352个文件;DuckLake不产生数据文件(行内嵌于目录),避免了“小文件问题”,流式负载查询快926倍。
使用建议
应该使用外部表的场景:
- 冷数据归档、一次性或低频分析
- 希望利用廉价对象存储降低成本(最高可节省20倍)
- 需要直接查询数据湖中的开放格式文件,而不搬运数据
- 结合物化视图或dbt(如
dbt-external-tables包)使用
不适合使用外部表的场景:
- 事务型OLTP负载
- 每次查询都需要亚秒级延迟
- 数据极小,外部管理的开销超过加载收益
最终结论
外部表并非“过时技术”,反而在湖仓一体时代重新成为核心模式。从最早读取CSV到如今支持ACID表格式,其“数据原地访问”的本质始终未变。Lindy效应表明:一项技术存在越久,预计未来还能存在同样久。外部表已历经25年并不断被重写,未来仍将长期活跃。正如作者所言:“现代外部表已经不‘外部’了——它正重新成为数据库语义的一部分。”
