文章目录
- [为什么 IRIS SQL 会比 Spring JDBC 更快?](#为什么 IRIS SQL 会比 Spring JDBC 更快?)
- [1. **数据库执行层级不同:IRIS SQL 是原生执行,而 Spring JDBC 只是"调用者"**](#1. 数据库执行层级不同:IRIS SQL 是原生执行,而 Spring JDBC 只是“调用者”)
-
-
- [Spring JDBC 的执行路径:](#Spring JDBC 的执行路径:)
- [IRIS 的执行路径(核心差异):](#IRIS 的执行路径(核心差异):)
-
- [2. **IRIS 的存储引擎(Globals)结构天生比传统关系型数据库快**](#2. IRIS 的存储引擎(Globals)结构天生比传统关系型数据库快)
- [3. IRIS 查询流程(极简)](#3. IRIS 查询流程(极简))
- [4. 基本概念:什么是 Global?](#4. 基本概念:什么是 Global?)
-
-
- 底层存储与组织(高层抽象)
- 访问模式与操作语义(为何高效)
- [常用 Global 操作(ObjectScript 示例)](#常用 Global 操作(ObjectScript 示例))
- [与 SQL/类映射关系](#与 SQL/类映射关系)
- [示例:用 Global 实现一个简单索引并比较访问(思路示例)](#示例:用 Global 实现一个简单索引并比较访问(思路示例))
-
- [5. Globals 结构比页结构(Page)快太多:稀疏、有序、按键直接定位](#5. Globals 结构比页结构(Page)快太多:稀疏、有序、按键直接定位)
- [6 . 索引本质上是 Global(稀疏多维数组),天然有序,遍历速度极快](#6 . 索引本质上是 Global(稀疏多维数组),天然有序,遍历速度极快)
- [7. IRIS 的执行路径极短:SQL 层非常薄,没有大量中间对象](#7. IRIS 的执行路径极短:SQL 层非常薄,没有大量中间对象)
- [8. 示例一:单条查询路径对比(IRIS vs MySQL/PostgreSQL)](#8. 示例一:单条查询路径对比(IRIS vs MySQL/PostgreSQL))
-
-
- [MySQL/Postgres 查询一条记录的路径(非常多层)](#MySQL/Postgres 查询一条记录的路径(非常多层))
- [IRIS 查找一条记录(几乎无中间层)](#IRIS 查找一条记录(几乎无中间层))
- [对比示例(读取某个用户 ID=123)](#对比示例(读取某个用户 ID=123))
-
- [MySQL/PostgreSQL 内部做的事情:](#MySQL/PostgreSQL 内部做的事情:)
- [IRIS 内部做的事情:](#IRIS 内部做的事情:)
-
- 性能差距示例
-
-
- [同样是查询 100 万条数据中的一条](#同样是查询 100 万条数据中的一条)
-
- [9 什么是 IRIS 的箭头语法(→)?](#9 什么是 IRIS 的箭头语法(→)?)
-
- [传统数据库 JOIN 在多表时的结构问题](#传统数据库 JOIN 在多表时的结构问题)
-
- [1. 扫描或索引查找 table A](#1. 扫描或索引查找 table A)
- [2. 扫描或索引查找 table B](#2. 扫描或索引查找 table B)
- [3. 构建临时 JOIN buffer / Hash table / Merge buffer](#3. 构建临时 JOIN buffer / Hash table / Merge buffer)
- [4. 比较 key](#4. 比较 key)
- [5. 输出结果](#5. 输出结果)
- [10. IRIS 的箭头语法为什么快?](#10. IRIS 的箭头语法为什么快?)
- [🟦 直观对比:同样的 3 表查询](#🟦 直观对比:同样的 3 表查询)
- [🟢 IRIS 箭头语法:](#🟢 IRIS 箭头语法:)
- [🔥 性能差距巨大](#🔥 性能差距巨大)
-
- [**1. 箭头语法基于"对象引用",不是基于 JOIN**](#1. 箭头语法基于“对象引用”,不是基于 JOIN)
- [**2. 箭头语法直接利用 IRIS 的 Global 多层树结构**](#2. 箭头语法直接利用 IRIS 的 Global 多层树结构)
- [**3. 多表访问的成本是"节点跳转",而不是"多表 join"**](#3. 多表访问的成本是“节点跳转”,而不是“多表 join”)
- [**4. 箭头语法可以无限深度引用**](#4. 箭头语法可以无限深度引用)
- [**5. 执行计划简单、可预测、稳定**](#5. 执行计划简单、可预测、稳定)
- [🧪 示例:深度 4 层引用](#🧪 示例:深度 4 层引用)
-
- [🎯 为什么 IRIS 箭头语法查询多表比传统 SQL 更快?](#🎯 为什么 IRIS 箭头语法查询多表比传统 SQL 更快?)
- [11. 传统数据库:复杂关系 = 多表 Join = 性能瓶颈 & 开发复杂](#11. 传统数据库:复杂关系 = 多表 Join = 性能瓶颈 & 开发复杂)
- [IRIS:使用 Global(天然多维索引结构)可以直接定位值](#IRIS:使用 Global(天然多维索引结构)可以直接定位值)
-
-
- [🔥 IRIS 中读取复杂关系只需要:](#🔥 IRIS 中读取复杂关系只需要:)
-
- [3. 性能差异举例(真实结构对比)](#3. 性能差异举例(真实结构对比))
-
-
- [假设要获取订单 → 用户 → 地址完整信息](#假设要获取订单 → 用户 → 地址完整信息)
- [🔷 MySQL/PostgreSQL 的执行路径](#🔷 MySQL/PostgreSQL 的执行路径)
- [🔷 IRIS Globals 的执行路径](#🔷 IRIS Globals 的执行路径)
-
- [4. 举例说明速度差异](#4. 举例说明速度差异)
-
-
- [MySQL 的 join 查询:](#MySQL 的 join 查询:)
- [IRIS Global 查找:](#IRIS Global 查找:)
-
- [5. 为什么 IRIS 可以直接取值?](#5. 为什么 IRIS 可以直接取值?)
- [6. IRIS 多表复杂关系开发的优势总结](#6. IRIS 多表复杂关系开发的优势总结)
- [7. 最形象的比喻(特别精准)](#7. 最形象的比喻(特别精准))
-
-
- MySQL/PostgreSQL:
- [IRIS Globals:](#IRIS Globals:)
-
- 总结(最核心一句话)
为什么 IRIS SQL 会比 Spring JDBC 更快?
IRIS 是"内存+持久化融合"的多模型数据库,执行 SQL 时不需要走 Java ORM 那些复杂的转换层,它是原生运行在数据库内核的高性能引擎。
1. 数据库执行层级不同:IRIS SQL 是原生执行,而 Spring JDBC 只是"调用者"
Spring JDBC 的执行路径:
Java → JDBC driver → 网络传输 → DB → SQL 解析 → 执行 → 返回结果 → JDBC → Java对象映射
每一步都要:
- 进行数据序列化/反序列化
- 做对象创建
- 做数据类型转换
- 消耗 GC
- 走网络 TCP 调用
总传输和转换成本很高
IRIS 的执行路径(核心差异):
IRIS SQL 执行在 数据库内核 ,且底层语言是 高性能的原生运行时(ObjectScript 运行在数据库层面)
- 不需要 Java 层处理
- 不需要 ORM/JDBC 的多层映射
- 不需要大量对象转换
- SQL 优化器与存储引擎强绑定(类似 Oracle 内核)
- 执行路径短得多
这是数据库层的"本地执行" VS Java API 的"远程调用"
自然会快很多。
2. IRIS 的存储引擎(Globals)结构天生比传统关系型数据库快
IRIS 不像 MySQL、PostgreSQL 那样使用:
- page
- tuple
- B-tree page 分裂
- buffer pool
- redo log + binlog
- MVCC / snapshot
IRIS 使用它独有的 Globals(基于平衡树的稀疏多维数组)。
特性:
| 部署 | IRIS Globals | 传统 RDBMS B-tree |
|---|---|---|
| 插入 | O(log N),无 page 结构 | page 分裂、页锁、buffer flush |
| 查询 | 单节点定位,速度极快 | 要经过 buffer pool, page lookup |
| 存储 | 无固定页结构,高压缩率 | 页固定16KB / 8KB |
| 并发 | 无 MVCC 压力 | MVCC、写放大、WAL |
📌 IRIS 数据查找和更新本质是对多维树的直接定位,几乎没有中间层。
传统数据库每一步都会经历:
buffer pool → page → tuple → redo log → WAL
而 IRIS 没有这些复杂结构,所以 SQL 执行天然就快 🚀。
3. IRIS 查询流程(极简)
一个 SQL 查询最终会变成对 Globals 的访问:
sql
直接定位键 → 读取节点
例如:
sql
SELECT Name FROM Person WHERE ID = 1001
直接对应:
sql
^PersonD(1001,"Name")
访问路径非常短:
sql
Global Tree → 找到这个键 → 返回
没有 "页 → tuple → 行格式 → 版本解析 → buffer pool" 的步骤。
4. 基本概念:什么是 Global?
-
逻辑模型:Global 看起来就是一个多维数组(多级下标)。例如:
sqlSET ^Person(100,"name") = "张三" SET ^Person(100,"age") = 30这里
^Person是 global 名称,100,"name"是 subscripts(下标)。 -
稀疏:你可以只写你需要的下标,整个空间是稀疏的,不需要连续分配内存。
-
持久化:写入的 global 被写到磁盘(global database 文件)并由 IRIS 管理其持久化、回滚与恢复。
-
键值定位:每个存取都是"基于键"的操作(直接定位),不像关系数据库需要扫描页/行后再解析字段。
底层存储与组织(高层抽象)
注意:下面是对实现的高层、可理解的抽象说明(避免过度承诺具体内部实现细节),目的是帮助理解行为与性能。
- 树/键结构 :Globals 在磁盘上以一种可按下标顺序索引的树/键结构存储(引擎提供对下标的快速查找和按序迭代能力)。
- Extent(区段)管理:物理磁盘空间按 extent 分配,数据写入在这些 extent 中连续存放以提高 I/O 效率。
- 稀疏键空间 :下标本质上被拼成排序键(按字典序/字节序),这样引擎能在键空间上做快速定位与范围扫描(比如
$ORDER/$QUERY)。 - 内存缓存:常用的 global 节点被缓存在内存(缓存管理),减少磁盘 I/O。
- Journal / 日志:为保证持久性,写操作会记录到 journal(写前日志或类似机制)以支持崩溃恢复与回滚。
访问模式与操作语义(为何高效)
- O(log N) 或接近 O(1) 的键定位 :访问某个具体键(例如
^G(a,b,c))不需要扫描整表,可以直接定位到对应节点或其附近位置。 - 按键顺序高效遍历 :函数
$ORDER(^G(key))、$QUERY等允许从某个位置顺序遍历下一/上一个键,效率很高,适合范围查询与顺序扫描。 - 原子性和事务性:对 Global 的写操作在事务内受 ACID 支持,可以回滚、提交且与 journaling 结合保证恢复。
- 细粒度锁/乐观并发:引擎采用可以支持高并发的锁机制(局部锁或 MVCC 风格的并发控制),避免全局阻塞。
常用 Global 操作(ObjectScript 示例)
sql
; 写入
SET ^Orders(1001,"status") = "NEW"
SET ^Orders(1001,"amount") = 299.5
; 读取
WRITE ^Orders(1001,"status")
; 遍历订单 id
SET id = ""
FOR SET id = $ORDER(^Orders(id)) QUIT:id="" DO
. WRITE "Order:", id, " status=", ^Orders(id,"status"), !
$ORDER:按字典序得到下一个(或上一个)下标。$QUERY:在一些实现中提供比$ORDER更高效的顺序遍历(依据版本差异)。
与 SQL/类映射关系
- SQL 表/列并不是另存的 :当你用 SQL
CREATE TABLE或 %Persistent 类时,IRIS 实际上在底层把表/索引映射到 Global 的某些节点布局上。也就是说 SQL 行/列/索引是 Global 的一个结构化视图或映射。 - 索引:SQL 索引对应的也会是在另一个 global 中建立的键(反向映射),因此索引扫描同样是基于 global 键定位的高效操作。
- 无缝跨模型访问:ObjectScript、SQL、Native routines 都能直接操作同样的 Global,因此没有数据复制、序列化开销。
示例:用 Global 实现一个简单索引并比较访问(思路示例)
假设有 ^User(id,"name") 和需要按 name 查询 id:
- 直接按 id 找:
SET id=123 WRITE ^User(id,"name")------ 直接定位,最快。 - 按 name 找 id:可以维护一个索引 global
^NameIndex(name,id)=1:- 写入时同时更新
^NameIndex(name,id)=1 - 查询时
$ORDER(^NameIndex("Alice",id))找到对应 id,然后直接去^User(id,...)读取。
- 写入时同时更新
这种做法把一个"按 name 查询"的昂贵操作转变为两个高效的键定位操作。
5. Globals 结构比页结构(Page)快太多:稀疏、有序、按键直接定位
传统数据库 I/O 模型:
sql
读取一行 → 必须读整个数据页(8KB / 16KB)
IRIS 的 Global 模型:
sql
只读需要的节点,不需要读整个页
键顺序天然可排序
优点:
| MySQL/PG(页结构) | IRIS Globals(键结构) |
|---|---|
| 对某一行的读会触发整页 I/O | 只读需要的节点 |
| row format 解码 | 无需解码 |
| NULL bitmap / tuple header | 无额外的元数据负担 |
| 页分裂昂贵 | 键插入更局部化 |
| 索引 B-tree + 行指针 | 索引本身是 global(键 → 主键) |
这是 IRIS 在点查、范围查、索引查方面普遍更快的核心原因。
6 . 索引本质上是 Global(稀疏多维数组),天然有序,遍历速度极快
MySQL/PG 的 B-tree 索引:
- page split
- tuple decode
- pointer 跳转
- buffer pool miss → page I/O
IRIS 的索引结构本质是:
sql
^Index("lastname", "Zhang", 1001) = ""
^Index("lastname", "Zhang", 1033) = ""
特点:
- 连续键顺序存放,范围扫描超快
- 键按字节序排序,无需额外排序
- 节点小,I/O 少
- 直接定位,无行格式开销
典型查询:
sql
SELECT * FROM Person WHERE lastname='Zhang'
在 IRIS 中转化为:
sql
遍历 ^Index("lastname","Zhang",*)
对每个 id 直接取 ^Person(id,*)
比 MySQL/PG 少了至少 两层 跳转和格式解码。
7. IRIS 的执行路径极短:SQL 层非常薄,没有大量中间对象
Java MySQL 驱动访问路径:
sql
Java → JDBC → SQL Parse → Plan → Executor → Row → Column → Java对象
IRIS 访问路径:
sql
Java → JDBC → SQL → 直接取 global 节点(立即可用)
没有:
- Row对象
- Column对象
- 字段解码成本
- 元数据构建成本
对比:
| 操作 | MySQL/PG 成本 | IRIS 成本 |
|---|---|---|
| 取整数 | 解码、拷贝、对象包装 | 直接从 global 读取 |
| 取字符串 | 变长字段解析 | 已经按字符串存放 |
| 范围查询 | B-tree page scan | 直接键顺序遍历 |
8. 示例一:单条查询路径对比(IRIS vs MySQL/PostgreSQL)
MySQL/Postgres 查询一条记录的路径(非常多层)
sql
SQL -> Parser -> Optimizer
-> Buffer Pool -> Page(8KB/16KB)
-> Page directory -> Slot -> Tuple
-> MVCC Snapshot
-> WAL/Redo consistency checks
-> 返回结果
层级数 ≈ 7~12 层
IRIS 查找一条记录(几乎无中间层)
sql
SQL -> Parser -> Optimizer
-> 直接定位到 Global 节点
-> 返回结果
层级数 ≈ 3 层
对比示例(读取某个用户 ID=123)
MySQL/PostgreSQL 内部做的事情:
sql
1. 找索引页 B-tree
2. Buffer pool 是否命中?不命中则读磁盘
3. 索引页内二分查找定位 tuple id
4. 去数据页 (heap page) 找 tuple
5. 检查 MVCC(是否被删除?是否可见?)
6. 扫描 undo log 以还原 snapshot
7. 返回结果
→ 即使只有 1 行记录,也要经过多个 page、多次跳转、MVCC 判断。
IRIS 内部做的事情:
IRIS Orders 数据会这样存储在 Global:
sql
^Orders(123) = "John|2024-02-03|PAID"
查找:
sql
Get ^Orders(123)
就这么一句。
没有 page、没有 tuple、没有 undo、没有 MVCC snapshot。
性能差距示例
同样是查询 100 万条数据中的一条
| 项目 | MySQL/PostgreSQL(B-tree) | IRIS(Globals) |
|---|---|---|
| 查找成本 | log(N) 在 B-tree 中跳页 | log(N) 但无 page,只是树节点 |
| 每层的代价 | 页命中/磁盘 IO | 内存节点 |
| 一次查找路径 | 3~6 个 page | 1~3 个节点 |
| MVCC | 必须检查可见性 | 无需检查 |
| 最终速度 | ⭐ 30~800 微秒 | ⭐ 1~20 微秒 |
IRIS 速度是 数量级 优势,因为中间层少到极致。
9 什么是 IRIS 的箭头语法(→)?
IRIS 独有的简写查询语法:
sql
SELECT Name, Home.City -> Name
FROM Person
表示:
Home是引用(类似外键)→ Name表示自动"跳转"到关联对象的名称
它本质上不是 JOIN。
而是:
直接通过对象指针查找关联记录,属于一次 Global 多维树的直接定位。
和传统数据库 JOIN 完全不同。
传统数据库 JOIN 在多表时的结构问题
传统数据库(MySQL/PostgreSQL/Oracle)JOIN 必须:
1. 扫描或索引查找 table A
2. 扫描或索引查找 table B
3. 构建临时 JOIN buffer / Hash table / Merge buffer
4. 比较 key
5. 输出结果
JOIN 越多:
- 需要越多的中间结构
- JOIN 顺序极其重要
- 执行计划变复杂
- 内存 buffer 越大
- IO 越多
- SQL 优化难度成倍增加
越多表 = 越慢。
10. IRIS 的箭头语法为什么快?
因为 IRIS 底层不是基于表,也不是 JOIN。
IRIS 使用:
面向对象的引用结构 + 多维 Globals 树
查询关联数据 = 节点路径跳转(非常快)
一个箭头跳转(→)相当于:
- 去对象的 OID 映射表查一次(O(log N))
- 直接定位到对应的 Global 节点
- 读取数据(几十~几百字节)
没有 JOIN、没有 buffer、没有排序、没有临时表。
🟦 直观对比:同样的 3 表查询
假设 3 个表:
- Person
- Address
- Country
传统 SQL:
sql
SELECT p.Name, a.City, c.Name
FROM Person p
JOIN Address a ON p.AddressID = a.ID
JOIN Country c ON a.CountryID = c.ID
需要 2 次 JOIN:
- JOIN Person → Address
- JOIN Address → Country
优化器要决定:
- Hash join? Merge join? Nested loop?
- 哪个表先?
- 哪个表驱动?
- 有没有索引?
- 内存是否足够?
复杂,昂贵,容易退化。
🟢 IRIS 箭头语法:
sql
SELECT Name, Address -> City, Address -> Country -> Name
FROM Person
解释:
Address -> City= 找 Address 关联对象,取 City 字段Address -> Country -> Name= 连续跳转两层
这不是 JOIN。
而是:
| 步骤 | IRIS 做的事情 |
|---|---|
| 1 | 获取 Person OID |
| 2 | 跳到 Address OID(一次 Global 查找) |
| 3 | 取 City |
| 4 | 跳到 Country OID |
| 5 | 取 Country Name |
全部都是 O(log N) 节点级访问,没有 JOIN。
🔥 性能差距巨大
| 项目 | 传统数据库 JOIN | IRIS 箭头语法 |
|---|---|---|
| 结构类型 | 表 + 行 + 页 | 对象引用 + 全局树节点 |
| 算法 | JOIN(O(N logN) 或 worse) | 直接定位(O(logN)) |
| 中间结果 | 大量临时表、哈希表 | 完全没有 |
| CPU | 高 | 很低 |
| 内存 | JOIN buffer | 几乎无 |
| IO | 要访问多个表的页 | 一个节点一个节点访问 |
| 多层深度 | 指数级变慢 | 几乎线性(跳一次节点) |
| SQL 复杂度 | 指数增加 | 简洁不变 |
当 join 超过 4~5 张表时:
- MySQL/PostgreSQL 会非常吃力
- IRIS 则基本无压力(只是多个 O(logN) 跳转)
1. 箭头语法基于"对象引用",不是基于 JOIN
所以跳转不依赖临时结构。
2. 箭头语法直接利用 IRIS 的 Global 多层树结构
存储结构天生适合多层引用。
3. 多表访问的成本是"节点跳转",而不是"多表 join"
成本随层数线性增长,而不是指数增长。
4. 箭头语法可以无限深度引用
传统数据库 JOIN 超过 7~10 层就难以优化。
5. 执行计划简单、可预测、稳定
不像 JOIN 可能因为统计信息变动突然退化。
🧪 示例:深度 4 层引用
传统 SQL:
sql
SELECT p.Name, c.Name, r.Name, z.Name
FROM Person p
JOIN City c ON p.CityID = c.ID
JOIN Region r ON c.RegionID = r.ID
JOIN Zone z ON r.ZoneID = z.ID
IRIS 箭头语法:
sql
SELECT Name,
City -> Name,
City -> Region -> Name,
City -> Region -> Zone -> Name
FROM Person
传统数据库:
4 个 JOIN = 执行计划复杂、大量 IO、中间表、排序风险
IRIS:
4 次节点跳转 → 非常轻量
🎯 为什么 IRIS 箭头语法查询多表比传统 SQL 更快?
| 原因 | 解释 |
|---|---|
| 不是 JOIN | IRIS 使用对象指针跳转,不生成任何临时 join 结构 |
| 不按"表 + 行 + 页"访问 | IRIS 访问的是全局节点,粒度极小 |
| 多表 = 多次节点跳转 | 而不是 JOIN 复杂度增长 |
| 无 Hash/Merge/Nested-loop 开销 | 因为根本不需要 |
| 无排序 / 临时表 | 跳转 = O(logN) 数百字节 IO |
| 执行计划更稳定 | 不受统计信息等因素影响 |
| 更适合复杂层级结构 | 深层引用比传统数据库 JOIN 快几个数量级 |
多张表复杂关系时,为什么 IRIS 使用 ObjectScript + Globals 的开发方式,能比传统数据库(MySQL/PostgreSQL)用 SQL Join 更高效、更简单。
11. 传统数据库:复杂关系 = 多表 Join = 性能瓶颈 & 开发复杂
在 MySQL/PostgreSQL 里,复杂数据关系通常写成:
sql
SELECT o.id, o.total, c.name, a.street, a.city
FROM orders o
JOIN customers c ON o.customer_id = c.id
JOIN addresses a ON c.address_id = a.id
WHERE o.id = 1001;
数据库内部要做:
- 解析 SQL
- 构建执行计划
- 访问多个页(page)
- 在 B-tree 上查找多次
- 做多个 Join(Nested Loop / Hash Join)
- 从 buffer pool 取 page
- 做 MVCC 快照一致性检查
- 可能产生临时表
📌 即便字段是索引,也要走很多层:page → tuple → row → join → filter → return
IRIS:使用 Global(天然多维索引结构)可以直接定位值
假设我们有如下 Global 结构:
sql
^Order(orderId) = $lb(customerId, total)
^Customer(customerId) = $lb(name, addressId)
^Address(addressId) = $lb(street, city)
三张表的关系其实在树结构中是已经拆好了。
🔥 IRIS 中读取复杂关系只需要:
sql
SET order = ^Order(1001)
SET customer = ^Customer($LISTGET(order, 1))
SET address = ^Address($LISTGET(customer, 2))
WRITE "订单金额: ", $LISTGET(order, 2), !
WRITE "客户姓名: ", $LISTGET(customer, 1), !
WRITE "客户城市: ", $LISTGET(address, 2), !
📌 没有 Join
📌 没有 page lookup
📌 没有 tuple decode
📌 没有 MVCC
📌 直接通过节点路径取得数据
速度 = 树结构 O(logN) 定位 → 立即读出。
3. 性能差异举例(真实结构对比)
假设要获取订单 → 用户 → 地址完整信息
🔷 MySQL/PostgreSQL 的执行路径
sql
SQL Parser
→ Optimizer
→ Join Plan (Hash Join)
→ B-tree lookup (orders)
→ B-tree lookup (customers)
→ B-tree lookup (addresses)
→ Construct result row
→ Return
SQL 越复杂,Join 越多,性能呈指数下降。
🔷 IRIS Globals 的执行路径
sql
^Order → direct key lookup
^Customer → direct key lookup
^Address → direct key lookup
Return
无需优化器sql
无需 Join
无需 tuple decode
无需 page IO
无需 MVCC / WAL
树结构天然就是索引
4. 举例说明速度差异
假设 500 万订单、500 万客户、500 万地址。
MySQL 的 join 查询:
sql
SELECT ... FROM orders
JOIN customers ...
JOIN address ...
WHERE orders.id = X;
执行:
- 三次 B-tree 查找(每次可能访问多个 page)
- Join 逻辑消耗 CPU
- 需要构建 Row 格式
- 需要 tuple 解码
- 需要 MVCC 检查
- 有 buffer pool miss 时还需磁盘 IO
耗时常见:3--20ms
IRIS Global 查找:
sql
SET order = ^Order(X)
SET customer = ^Customer($LISTGET(order,1))
SET address = ^Address($LISTGET(customer,2))
执行:
- 三次树节点直接读(通常在内存中)
- 无 join、无 MVCC、无 page
耗时:0.05--0.2ms
👉 理论上快 20~100 倍
👉 这还是单线程,不用优化器
5. 为什么 IRIS 可以直接取值?
因为 Globals 不是传统数据库的"数据页 + 行 + 列"的结构。
它是:
- 稀疏多维数组
- 树形结构(平衡 B-tree)
- 每个节点就是 key/value
- 天然支持多维索引
例如:
sql
^Order(1001,"Customer","Name") = "张三"
^Order(1001,"Customer","City") = "上海"
你可以直接访问:
sql
WRITE ^Order(1001,"Customer","City")
📌 你可以随意设计树节点结构,只取你要的路径
📌 不需要扫描行或构建 RowObject
📌 不需要访问多个 page
📌 没有冗余字段解码
传统数据库必须 select row → parse tuple → map column → join → output
IRIS 则是 一步直达节点。
6. IRIS 多表复杂关系开发的优势总结
| 项目 | 传统 RDBMS(MySQL/PostgreSQL) | IRIS(Globals + ObjectScript) |
|---|---|---|
| 数据结构 | 表 & 行 & 页 | 多维树 Globals |
| 多表查询 | Join 是必需的 | 直接取节点,无需 Join |
| 性能瓶颈 | Join、page IO、MVCC | 直接定位节点,无中间层 |
| 复杂业务逻辑 | SQL 里难写 | ObjectScript 对树操作非常简单 |
| 扩展性 | 修改 schema 成本高 | Global 可随意添加新维度 |
| 维护成本 | 复杂 SQL 难维护 | 树结构天然表达关系 |
| 性能优化 | 索引、缓存、执行计划 | Global = 天然索引结构 |
7. 最形象的比喻(特别精准)
MySQL/PostgreSQL:
像是你要找一份文件:
- 先到 A 档案柜(order)翻文件夹
- 再去 B 档案柜(customer)找对照
- 再去 C 档案柜(address)找地址
- 再把三个结果拼成 PDF 返回
耗时自然很高。
IRIS Globals:
所有数据都在一棵大树里,路径已经预先规划:
sql
/Order/1001/Customer/Address
你只要顺着树拿值,不需要 Join 拼接。
就是 直接跳到精确坐标取出数据。
总结(最核心一句话)
IRIS 在多表复杂查询时快,是因为 Global 把数据拆成多维树结构,使得跨表数据可以 O(logN) 直接定位,无需 SQL Join、无需访问 page、无需 MVCC,也无需解码 tuple。