SQL数据库核心原理解析_关系模型与执行引擎

8次阅读

SQL 数据库的核心是关系模型与执行引擎:前者基于数学理论定义数据组织规则,后者将 SQL 转化为物理操作;二者共同决定 SQL 的正确性、性能与行为。

SQL 数据库核心原理解析_关系模型与执行引擎

SQL 数据库的核心在于两块:关系模型定义数据怎么组织,执行引擎决定查询怎么运行。理解这两者,才能真正看懂 SQL为什么 这样写、为什么慢、为什么报错。

关系模型:不只是“表”这么简单

关系模型不是简单把数据存成表格,而是建立在严格数学基础(集合论和谓词逻辑)上的抽象体系。它的核心是“关系”(relation),对应到数据库中就是一张表,但每张表必须满足几个关键约束:

  • 属性(列)有唯一名称且不可再分——不支持嵌套结构或 JSON 字段(除非用扩展类型);
  • 元组(行)无序,且不能重复——所以 ORDER BY 不是关系操作,去重要用 DISTINCT;
  • 每个属性有明确的数据类型和域(domain)——NULL 不是值,而是“缺失信息”的标记,参与比较时多数返回 UNKNOWN;
  • 主键与外键构成完整性约束——不是可选功能,而是维系关系语义的骨架,删除父记录前必须处理子引用。

正因如此,JOIN 不是“连两张表”,而是对两个关系做笛卡尔积后按条件筛选;GROUP BY 也不是“分组显示”,而是将输入关系划分为若干子集,每组输出一行聚合结果。

执行引擎:SQL 语句如何变成磁盘读写

你写的 SELECT 不会直接执行。它先被解析成语法树,再经由优化器生成执行计划,最后由执行器驱动存储层完成实际操作。这个过程里最关键的环节是:

  • 逻辑计划 → 物理计划的转换——比如优化器可能把 WHERE 条件下推到 JOIN 之前,把子查询转为 JOIN,甚至重排 JOIN 顺序以减少中间结果大小;
  • 算子实现方式决定性能——Hash Join 适合大表关联(需内存建哈希表),Merge Join 依赖排序,Nested Loop 适合小表驱动大表;
  • 统计信息驱动决策——表行数、列基数、直方图等信息影响索引是否被选中、是否走全表扫描;
  • 缓冲区与预读机制隐藏 I / O 成本——数据页常驻 Buffer Pool,顺序扫描会触发预读,但随机跳转访问仍可能频繁刷盘。

EXPLAIN(或 EXPLAIN ANALYZE)看到的“Index Scan”“Bitmap Heap Scan”等,都是物理算子名,背后对应不同的内存使用模式和磁盘访问路径。

关系模型与执行引擎如何互相制约

两者不是割裂的:模型决定了能表达什么,引擎决定了能多快、多稳地实现它。

  • 视图(VIEW)本质是保存的 SELECT 语句,没有独立存储——每次查询都重写并内联进主 SQL,可能让优化器错过更优路径;
  • 窗口函数(如 ROW_NUMBER())要求逻辑上“先分区排序再计算”,执行器必须维护滑动窗口状态,无法流式处理,内存压力明显;
  • 事务隔离级别(如 READ COMMITTED vs SERIALIZABLE)改变执行器加锁 / 版本控制策略,直接影响并发行为和性能,但不改变 SQL 语义本身;
  • NULL 语义渗透到所有比较和聚合中——COUNT(*)统计行数,COUNT(col)忽略 NULL,这要求执行器在扫描时实时判断空值,不能简单累加。

一个看似简单的 ORDER BY LIMIT 10,在没有索引时,引擎必须排序全部数据再取头十行;而关系模型只保证结果满足“有序 + 截断”,不承诺实现方式——这也正是优化器存在意义。

不复杂但容易忽略

写 SQL 时盯着语法,调性能时盯着执行计划,但真正卡住问题的,往往是模型和引擎之间的隐含契约:比如默认不启用并行查询、临时表未走内存、统计信息过期导致误判、或者把关系运算当成过程式逻辑来理解。抓住这两根主线,很多“奇怪现象”就自然清晰了。

text=ZqhQzanResources