From 5b8e5e7bd226aec90b365ad78a69fc2aae66f311 Mon Sep 17 00:00:00 2001 From: bourdon Date: Fri, 10 Oct 2025 18:49:57 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=87=E6=A1=A3=EF=BC=9A=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E5=92=8C=E4=BC=98=E5=8C=96=E9=A1=B9=E7=9B=AE=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 更新 DESIGN.md: - 强调强制 Schema(21 种类型) - 更新核心代码行数为 ~5,400 行 - 优化 ROW1 格式说明(英文) - 完善性能指标和项目成果 - 精简 DOCS.md 和 README.md - 统一文档风格和术语 --- DESIGN.md | 169 ++++++-------- DOCS.md | 66 +++--- README.md | 655 +++++++++--------------------------------------------- 3 files changed, 209 insertions(+), 681 deletions(-) diff --git a/DESIGN.md b/DESIGN.md index 2ed0d69..a0ac288 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -8,9 +8,9 @@ 1. **极简架构** - 放弃复杂的 LSM Tree 多层设计,使用简单的两层结构 2. **高并发写入** - WAL + MemTable 保证 200,000+ writes/s 3. **快速查询** - mmap B+Tree 索引 + 二级索引,1-5 ms 查询性能 -4. **低内存占用** - mmap 零拷贝,应用层内存 < 200 MB -5. **功能完善** - 支持 Schema、索引、条件查询等高级特性 -6. **生产可用** - 核心代码 5399 行,包含完善的错误处理和数据一致性保证 +4. **低内存占用** - mmap 零拷贝,应用层内存 < 150 MB +5. **功能完善** - 强制 Schema(21 种类型)、索引、条件查询等高级特性 +6. **生产可用** - 核心代码 ~5,400 行,包含完善的错误处理和数据一致性保证 ## 🏗️ 核心架构 @@ -19,10 +19,10 @@ │ SRDB Architecture │ ├─────────────────────────────────────────────────────────────┤ │ Application Layer │ -│ ┌───────────────┐ ┌──────────────────────────┐ │ -│ │ Database │->│ Table │ │ -│ │ (Multi-Table) │ │ (Schema + Storage) │ │ -│ └───────────────┘ └──────────────────────────┘ │ +│ ┌───────────────┐ ┌──────────────────────────┐ │ +│ │ Database │->│ Table │ │ +│ │ (Multi-Table) │ │ (Schema + Storage) │ │ +│ └───────────────┘ └──────────────────────────┘ │ ├─────────────────────────────────────────────────────────────┤ │ Write Path (High Concurrency) │ │ ┌─────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ @@ -50,8 +50,10 @@ │ │ │ - Leaf Nodes → Data Offset │ │ │ │ │ ├─────────────────────────────────────────┤ │ │ │ │ │ Data Blocks (Binary Format) │ │ │ -│ │ │ - 有 Schema: 二进制编码 │ │ │ -│ │ │ - 无 Schema: JSON 格式 │ │ │ +│ │ │ - ROW1 Format: Binary Encoding │ │ │ +│ │ │ [Magic:4B][Seq:8B][Time:8B] │ │ │ +│ │ │ [Fields:2B][OffsetTable][Data] │ │ │ +│ │ │ - Supports zero-copy & partial reads │ │ │ │ │ └─────────────────────────────────────────┘ │ │ │ │ │ │ │ │ Secondary Indexes (Optional) │ │ @@ -85,38 +87,6 @@ ## 📁 文件组织结构 -### 代码目录结构 - -``` -srdb/ ← 项目根目录 -├── go.mod ← 模块定义: code.tczkiot.com/wlw/srdb -├── DESIGN.md ← 本设计文档 -├── CLAUDE.md ← Claude Code 指导文档 -│ -├── database.go ← 数据库管理 (多表) -├── table.go ← 表管理 (带 Schema) -├── errors.go ← 错误定义和处理 -│ -├── wal.go ← WAL 实现 (Write-Ahead Log) -├── memtable.go ← MemTable 实现 (map + sorted slice) -├── sstable.go ← SSTable 文件 (读写器、管理器、编码) -├── btree.go ← B+Tree 索引 (构建器、读取器) -├── version.go ← 版本控制 (MANIFEST 管理) -├── compaction.go ← Compaction 压缩合并 -│ -├── schema.go ← Schema 定义与验证 -├── index.go ← 二级索引管理器 -├── index_btree.go ← 索引 B+Tree 实现 -├── query.go ← 查询构建器和表达式求值 -│ -├── examples/ ← 示例程序目录 -│ ├── webui/ ← Web UI 管理工具 -│ └── ... (其他示例) -│ -└── webui/ ← Web UI 静态资源 - └── ... -``` - ### 运行时数据目录结构 ``` @@ -152,16 +122,16 @@ database_dir/ ← 数据库目录 - 崩溃恢复支持 文件格式: -┌─────────────────────────────────────┐ -│ WAL Entry │ -├─────────────────────────────────────┤ -│ CRC32 (4 bytes) │ -│ Length (4 bytes) │ -│ Type (1 byte): Put │ -│ Key (8 bytes): _seq │ -│ Value Length (4 bytes) │ -│ Value (N bytes): 序列化的行数据 │ -└─────────────────────────────────────┘ +┌───────────────────────────────────────┐ +│ WAL Entry │ +├───────────────────────────────────────┤ +│ CRC32 (4 bytes) │ +│ Length (4 bytes) │ +│ Type (1 byte): Put │ +│ Key (8 bytes): _seq │ +│ Value Length (4 bytes) │ +│ Value (N bytes): Serialized row data │ +└───────────────────────────────────────┘ 性能: - 顺序写入: 极快 @@ -334,49 +304,65 @@ func (s *MmapSST) readNode(offset int64) *BTreeNode { - 零拷贝: 无内存分配 ``` -### 5. Schema 系统 (新增功能) +### 5. Schema 系统 ``` 设计: -- 类型定义和验证 -- 必填字段检查 -- 唯一性约束 -- 默认值支持 +- 强制 Schema(所有表必须定义) +- 21 种精确类型映射 +- Nullable 字段支持 +- 类型验证和转换 +- 索引标记(Indexed: true) + +支持的类型(21 种): +1. 有符号整数(5种): Int, Int8, Int16, Int32, Int64 +2. 无符号整数(5种): Uint, Uint8, Uint16, Uint32, Uint64 +3. 浮点数(2种): Float32, Float64 +4. 字符串(1种): String +5. 布尔(1种): Bool +6. 特殊类型(5种): Byte, Rune, Decimal, Time, Duration +7. 复杂类型(2种): Object (JSON), Array (JSON) 实现: type Schema struct { - Fields []FieldDefinition + TableName string + Fields []Field } -type FieldDefinition struct { +type Field struct { Name string - Type string // "string", "int", "float", "bool" - Required bool // 是否必填 - Unique bool // 是否唯一 - Default interface{} // 默认值 + Type FieldType // 21 种类型之一 + Indexed bool // 是否创建索引 + Nullable bool // 是否允许 NULL + Comment string // 字段注释 } func (s *Schema) Validate(data map[string]interface{}) error { - for _, field := range s.Fields { - // 检查必填字段 - // 检查类型匹配 - // 应用默认值 - } + // 1. 检查必填字段 + // 2. 类型验证和转换 + // 3. Nullable 检查 + // 4. 返回验证后的数据 } 使用示例: -schema := &schema.Schema{ - Fields: []schema.FieldDefinition{ - {Name: "name", Type: "string", Required: true}, - {Name: "age", Type: "int", Required: false}, - {Name: "email", Type: "string", Unique: true}, - }, -} +schema, _ := NewSchema("users", []Field{ + {Name: "name", Type: String, Indexed: false}, + {Name: "age", Type: Int32, Indexed: false}, + {Name: "email", Type: String, Indexed: true}, + {Name: "balance", Type: Decimal, Nullable: true}, +}) table, _ := db.CreateTable("users", schema) + +类型转换规则: +- 相同类型:直接接受 +- 兼容类型:自动转换(有符号 ↔ 无符号,需非负) +- 类型提升:整数 → 浮点 +- JSON 兼容:float64 → 整数(需为整数值) +- 负数 → 无符号:拒绝 ``` -### 6. 二级索引 (新增功能) +### 6. 二级索引 ``` 设计: @@ -472,7 +458,7 @@ qb.Where("email", query.EndsWith, "@gmail.com") 4. 返回匹配的行 ``` -### 8. 数据库和表管理 (新增功能) +### 8. 数据库和表管理 ``` 设计: @@ -607,27 +593,6 @@ Flush 流程 (后台): ## 📊 性能指标 -### 代码规模 -``` -核心代码: ~13,000 行 (不含测试和示例) -├── table.go: 表管理和存储引擎 -├── wal.go: WAL 实现 -├── memtable.go: MemTable 实现 -├── sstable.go: SSTable 文件读写 -├── btree.go: B+Tree 索引 -├── version.go: 版本控制 (MANIFEST) -├── compaction.go: Compaction 压缩 -├── index.go: 二级索引 -├── query.go: 查询构建器 -├── schema.go: Schema 验证 -├── errors.go: 错误处理 -└── database.go: 数据库管理 - -测试代码: ~2000+ 行 -示例代码: ~1000+ 行 -总计: 16,000+ 行 -``` - ### 写入性能 ``` 单线程: 50,000 writes/s @@ -884,8 +849,8 @@ SRDB 是一个功能完善的高性能 Append-Only 数据库引擎: - ✅ **高并发写入**: WAL + MemTable,200K+ w/s - ✅ **快速查询**: mmap B+Tree + 二级索引,1-5 ms - ✅ **低内存占用**: mmap 零拷贝,< 150 MB -- ✅ **功能完善**: Schema、索引、条件查询、多表管理 -- ✅ **生产可用**: 5399 行核心代码,完善的错误处理和数据一致性 +- ✅ **功能完善**: 强制 Schema(21 种类型)、索引、条件查询、多表管理 +- ✅ **生产可用**: ~5,400 行核心代码,完善的错误处理和数据一致性 - ✅ **简单可靠**: Append-Only,无更新/删除的复杂性 **技术亮点:** @@ -912,8 +877,8 @@ SRDB 是一个功能完善的高性能 Append-Only 数据库引擎: - ❌ 传统 OLTP 系统 **项目成果:** -- 核心代码: ~13,000 行 +- 核心代码: ~5,400 行(精简高效) - 测试代码: ~2,000+ 行 - 示例程序: 13+ 个完整示例 -- 文档: 完善的设计和使用文档 -- 性能: 达到设计目标 +- 文档: 完善的设计和使用文档(DESIGN.md、CLAUDE.md、DOCS.md、README.md) +- 性能: 达到设计目标(200K+ w/s 写入,1-5 ms 查询) diff --git a/DOCS.md b/DOCS.md index 7dd3cbc..dd7de36 100644 --- a/DOCS.md +++ b/DOCS.md @@ -12,7 +12,7 @@ - [Scan 方法](#scan-方法) - [Object 和 Array 类型](#object-和-array-类型) - [索引](#索引) -- [事务和并发](#事务和并发) +- [并发控制](#并发控制) - [性能优化](#性能优化) - [错误处理](#错误处理) - [最佳实践](#最佳实践) @@ -22,7 +22,7 @@ ## 概述 -SRDB (Simple Row Database) 是一个用 Go 编写的高性能嵌入式数据库,采用 LSM-Tree 架构,专为时序数据和高并发写入场景设计。 +SRDB (Simple Row Database) 是一个用 Go 编写的高性能嵌入式数据库,采用 Append-Only 架构(参考 LSM-Tree 设计理念),专为时序数据和高并发写入场景设计。 ### 核心特性 @@ -996,9 +996,7 @@ rows, _ := table.Query().Contains("name", "Alice").Rows() --- -## 事务和并发 - -### 并发控制 +## 并发控制 SRDB 使用 **MVCC (多版本并发控制)** 实现无锁并发读写: @@ -1036,18 +1034,6 @@ for i := 0; i < 100; i++ { wg.Wait() ``` -### 事务支持 - -⚠️ **当前版本不支持显式事务**,但保证: -- 单条写入的原子性(通过 WAL) -- 数据持久性(WAL fsync) -- 崩溃恢复(WAL 重放) - -未来版本计划支持: -- [ ] 显式事务 API -- [ ] 批量操作的原子性 -- [ ] ACID 保证 - --- ## 性能优化 @@ -1310,34 +1296,52 @@ table.Insert(data) // 错误未处理 ## 架构细节 -### LSM-Tree 结构 +### Append-Only 架构 + +SRDB 采用 Append-Only 架构(参考 LSM-Tree 设计理念),分为两层: + +1. **内存层** - WAL + MemTable (Active + Immutable) +2. **磁盘层** - 带 B+Tree 索引的 SST 文件,分层存储(L0-L3) ``` 写入流程: -数据 → WAL(持久化)→ MemTable → Immutable MemTable → Level 0 SST → Compaction → Level 1-6 +数据 → WAL(持久化)→ MemTable → Flush → SST L0 → Compaction → SST L1-L3 + +读取流程: +查询 → MemTable(O(1))→ Immutable MemTables → SST Files(B+Tree) ``` ### 文件组织 ``` database_dir/ -├── database.meta # 数据库元数据 -├── MANIFEST # 版本控制 -└── table_name/ - ├── schema.json # 表 Schema - ├── MANIFEST # 表级版本控制 - ├── 000001.wal # WAL 文件 - ├── 000001.sst # SST 文件 - ├── 000002.sst - └── idx_email.sst # 索引文件 +├── database.meta # 数据库元数据 +└── table_name/ # 每表一个目录 + ├── schema.json # 表 Schema 定义 + ├── MANIFEST-000001 # 表级版本控制 + ├── CURRENT # 当前 MANIFEST 指针 + ├── wal/ # WAL 子目录 + │ ├── 000001.wal # WAL 文件 + │ └── CURRENT # 当前 WAL 指针 + ├── sst/ # SST 子目录(L0-L3 层级文件) + │ └── 000001.sst # SST 文件(B+Tree + 数据) + └── idx/ # 索引子目录 + └── idx_email.sst # 二级索引文件 ``` +### 设计特点 + +- **Append-Only** - 无原地更新,简化并发控制 +- **MemTable** - `map[int64][]byte + sorted slice`,O(1) 读写 +- **SST 文件** - 4KB 节点的 B+Tree,mmap 零拷贝访问 +- **二进制编码** - ROW1 格式,无压缩,优先查询性能 +- **Compaction** - 后台异步合并,按层级管理文件大小 + ### Compaction 策略 -- **Level 0**: 文件数量 ≥ 4 触发 -- **Level 1-6**: 总大小超过阈值触发 +- **Level 0-3**: 文件数量或总大小超过阈值时触发 - **Score 计算**: `size / max_size` 或 `file_count / max_files` -- **文件大小**: L0=2MB, L1=10MB, L2=50MB, L3=100MB, L4+=200MB +- **文件大小**: L0=2MB, L1=10MB, L2=50MB, L3=100MB ### 性能指标 diff --git a/README.md b/README.md index 13e3204..926ef3e 100644 --- a/README.md +++ b/README.md @@ -1,48 +1,28 @@ # SRDB - Simple Row Database -[![Go Version](https://img.shields.io/badge/Go-1.24+-00ADD8?style=flat&logo=go)](https://golang.org/) +[![Go Version](https://img.shields.io/badge/Go-1.21+-00ADD8?style=flat&logo=go)](https://golang.org/) [![License](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE) -一个基于 LSM-Tree 的高性能嵌入式数据库,专为时序数据和日志存储设计。 +一个用 Go 编写的高性能 Append-Only 时序数据库引擎,专为高并发写入和快速查询设计。 -## 🎯 特性 +## 🎯 核心特性 -### 核心功能 -- **LSM-Tree 架构** - 高效的写入性能和空间利用率 -- **MVCC 并发控制** - 支持多版本并发读写 -- **WAL 持久化** - 写前日志保证数据安全 -- **自动 Compaction** - 智能的多层级数据合并策略 -- **索引支持** - 快速的字段查询能力 -- **Schema 管理** - 灵活的表结构定义,支持 21 种类型 -- **复杂类型** - 原生支持 Object(map)和 Array(slice) - -### 查询能力 -- **链式查询 API** - 流畅的查询构建器 -- **丰富的操作符** - 支持 `=`, `!=`, `<`, `>`, `IN`, `BETWEEN`, `CONTAINS` 等 -- **复合条件** - `AND`, `OR`, `NOT` 逻辑组合 -- **字段选择** - 按需加载指定字段,优化性能 -- **游标模式** - 惰性加载,支持大数据集遍历 +- **Append-Only 架构** - WAL + MemTable + mmap B+Tree SST,简化并发控制 +- **强类型 Schema** - 21 种数据类型,包括 Object(map)和 Array(slice) +- **高性能写入** - 200K+ 写/秒(多线程),<1ms 延迟(p99) +- **快速查询** - <0.1ms(内存),1-5ms(磁盘),支持二级索引 - **智能 Scan** - 自动扫描到结构体,完整支持复杂类型 - -### 管理工具 -- **Web UI** - 现代化的数据库管理界面 -- **命令行工具** - 丰富的诊断和维护工具 -- **实时监控** - LSM-Tree 结构和 Compaction 状态可视化 - ---- +- **链式查询 API** - 18 种操作符,支持复合条件 +- **自动 Compaction** - 后台异步合并,优化存储空间 +- **零拷贝读取** - mmap 访问 SST 文件,内存占用 <150MB +- **Web 管理界面** - 现代化的数据浏览和监控工具 ## 📋 目录 - [快速开始](#快速开始) -- [基本用法](#基本用法) -- [查询 API](#查询-api) - - [Scan 方法](#scan-方法---扫描到结构体) - - [Object 和 Array 类型](#object-和-array-类型) -- [Web UI](#web-ui) -- [架构设计](#架构设计) -- [性能特点](#性能特点) -- [开发指南](#开发指南) +- [核心概念](#核心概念) - [文档](#文档) +- [开发](#开发) --- @@ -54,6 +34,8 @@ go get code.tczkiot.com/wlw/srdb ``` +**要求**:Go 1.21+ + ### 基本示例 ```go @@ -73,12 +55,14 @@ func main() { } defer db.Close() - // 2. 定义 Schema + // 2. 定义 Schema(强类型,21 种类型) schema, err := srdb.NewSchema("users", []srdb.Field{ - {Name: "id", Type: srdb.Int64, Indexed: true, Comment: "用户ID"}, - {Name: "name", Type: srdb.String, Indexed: false, Comment: "用户名"}, + {Name: "id", Type: srdb.Uint32, Indexed: true, Comment: "用户ID"}, + {Name: "name", Type: srdb.String, Comment: "用户名"}, {Name: "email", Type: srdb.String, Indexed: true, Comment: "邮箱"}, - {Name: "age", Type: srdb.Int32, Indexed: false, Comment: "年龄"}, + {Name: "age", Type: srdb.Int32, Comment: "年龄"}, + {Name: "tags", Type: srdb.Array, Comment: "标签"}, // Array 类型 + {Name: "settings", Type: srdb.Object, Comment: "设置"}, // Object 类型 }) if err != nil { log.Fatal(err) @@ -92,555 +76,131 @@ func main() { // 4. 插入数据 err = table.Insert(map[string]any{ - "id": 1, + "id": uint32(1), "name": "Alice", "email": "alice@example.com", - "age": 25, + "age": int32(25), + "tags": []any{"golang", "database"}, + "settings": map[string]any{ + "theme": "dark", + "lang": "zh-CN", + }, }) if err != nil { log.Fatal(err) } - // 5. 查询数据 - rows, err := table.Query(). + // 5. 查询并扫描到结构体 + type User struct { + ID uint32 `json:"id"` + Name string `json:"name"` + Email string `json:"email"` + Age int32 `json:"age"` + Tags []string `json:"tags"` + Settings map[string]string `json:"settings"` + } + + var users []User + err = table.Query(). Eq("name", "Alice"). Gte("age", 18). - Rows() + Scan(&users) if err != nil { log.Fatal(err) } - defer rows.Close() - // 6. 遍历结果 - for rows.Next() { - row := rows.Row() - fmt.Printf("User: %v\n", row.Data()) - } + fmt.Printf("Found %d users\n", len(users)) + fmt.Printf("Tags: %v\n", users[0].Tags) + fmt.Printf("Settings: %v\n", users[0].Settings) } ``` --- -## 📖 基本用法 +## 💡 核心概念 -### 数据库操作 +### 架构 -```go -// 打开数据库 -db, err := srdb.Open("./data") +SRDB 使用 **Append-Only 架构**,分为两层: -// 列出所有表 -tables := db.ListTables() - -// 获取表 -table, err := db.GetTable("users") - -// 删除表 -err = db.DropTable("users") - -// 关闭数据库 -db.Close() -``` - -### 表操作 - -```go -// 插入数据 -err := table.Insert(map[string]any{ - "name": "Bob", - "age": 30, -}) - -// 获取单条数据(通过序列号) -row, err := table.Get(seq) - -// 删除数据 -err := table.Delete(seq) - -// 更新数据 -err := table.Update(seq, map[string]any{ - "age": 31, -}) -``` - -### Schema 定义 - -```go -schema, err := srdb.NewSchema("logs", []srdb.Field{ - { - Name: "level", - Type: srdb.String, - Indexed: true, - Comment: "日志级别", - }, - { - Name: "message", - Type: srdb.String, - Indexed: false, - Comment: "日志内容", - }, - { - Name: "timestamp", - Type: srdb.Int64, - Indexed: true, - Comment: "时间戳", - }, - { - Name: "metadata", - Type: srdb.Object, - Indexed: false, - Comment: "元数据(map)", - }, - { - Name: "tags", - Type: srdb.Array, - Indexed: false, - Comment: "标签(slice)", - }, -}) -``` - -**支持的字段类型**(21 种): - -**有符号整数**: -- `Int`, `Int8`, `Int16`, `Int32`, `Int64` - -**无符号整数**: -- `Uint`, `Uint8`, `Uint16`, `Uint32`, `Uint64` - -**浮点数**: -- `Float32`, `Float64` - -**基础类型**: -- `String` - 字符串 -- `Bool` - 布尔值 -- `Byte` - 字节(uint8) -- `Rune` - 字符(int32) - -**特殊类型**: -- `Decimal` - 高精度十进制(需要 shopspring/decimal) -- `Time` - 时间戳(time.Time) - -**复杂类型**: -- `Object` - 对象(map[string]xxx、struct{}、*struct{}) -- `Array` - 数组([]xxx 切片) - ---- - -## 🔍 查询 API - -### 基本查询 - -```go -// 等值查询 -rows, err := table.Query().Eq("name", "Alice").Rows() - -// 范围查询 -rows, err := table.Query(). - Gte("age", 18). - Lt("age", 60). - Rows() - -// IN 查询 -rows, err := table.Query(). - In("status", []any{"active", "pending"}). - Rows() - -// BETWEEN 查询 -rows, err := table.Query(). - Between("age", 18, 60). - Rows() -``` - -### 字符串查询 - -```go -// 包含 -rows, err := table.Query().Contains("message", "error").Rows() - -// 前缀匹配 -rows, err := table.Query().StartsWith("email", "admin@").Rows() - -// 后缀匹配 -rows, err := table.Query().EndsWith("filename", ".log").Rows() -``` - -### 复合条件 - -```go -// AND 条件 -rows, err := table.Query(). - Eq("status", "active"). - Gte("age", 18). - Rows() - -// OR 条件 -rows, err := table.Query(). - Where(srdb.Or( - srdb.Eq("role", "admin"), - srdb.Eq("role", "moderator"), - )). - Rows() - -// 复杂组合 -rows, err := table.Query(). - Where(srdb.And( - srdb.Eq("status", "active"), - srdb.Or( - srdb.Gte("age", 18), - srdb.Eq("verified", true), - ), - )). - Rows() -``` - -### 字段选择 - -```go -// 只查询指定字段(性能优化) -rows, err := table.Query(). - Select("id", "name", "email"). - Eq("status", "active"). - Rows() -``` - -### 结果处理 - -```go -// 游标模式(惰性加载) -rows, err := table.Query().Rows() -defer rows.Close() - -for rows.Next() { - row := rows.Row() - fmt.Println(row.Data()) -} - -// 获取第一条 -row, err := table.Query().First() - -// 获取最后一条 -row, err := table.Query().Last() - -// 收集所有结果 -data := rows.Collect() - -// 获取总数 -count := rows.Count() -``` - -### Scan 方法 - 扫描到结构体 - -SRDB 提供智能的 Scan 方法,完整支持 Object 和 Array 类型: - -```go -// 定义结构体 -type User struct { - Name string `json:"name"` - Email string `json:"email"` - Settings map[string]string `json:"settings"` // Object 类型 - Tags []string `json:"tags"` // Array 类型 -} - -// 扫描多行到切片 -var users []User -table.Query().Scan(&users) - -// 扫描单行到结构体(智能判断) -var user User -table.Query().Eq("name", "Alice").Scan(&user) - -// Row.Scan - 扫描当前行 -row, _ := table.Query().First() -var user User -row.Scan(&user) - -// 部分字段扫描(性能优化) -type UserBrief struct { - Name string `json:"name"` - Email string `json:"email"` -} -var briefs []UserBrief -table.Query().Select("name", "email").Scan(&briefs) -``` - -**Scan 特性**: -- ✅ 智能判断目标类型(切片 vs 结构体) -- ✅ 完整支持 Object(map)和 Array(slice)类型 -- ✅ 支持嵌套结构 -- ✅ 结合 Select() 优化性能 - -详细示例:[examples/scan_demo](examples/scan_demo/README.md) - -### 完整的操作符列表 - -| 操作符 | 方法 | 说明 | -|--------|------|------| -| `=` | `Eq(field, value)` | 等于 | -| `!=` | `NotEq(field, value)` | 不等于 | -| `<` | `Lt(field, value)` | 小于 | -| `>` | `Gt(field, value)` | 大于 | -| `<=` | `Lte(field, value)` | 小于等于 | -| `>=` | `Gte(field, value)` | 大于等于 | -| `IN` | `In(field, values)` | 在列表中 | -| `NOT IN` | `NotIn(field, values)` | 不在列表中 | -| `BETWEEN` | `Between(field, min, max)` | 在范围内 | -| `NOT BETWEEN` | `NotBetween(field, min, max)` | 不在范围内 | -| `CONTAINS` | `Contains(field, pattern)` | 包含子串 | -| `NOT CONTAINS` | `NotContains(field, pattern)` | 不包含子串 | -| `STARTS WITH` | `StartsWith(field, prefix)` | 以...开头 | -| `NOT STARTS WITH` | `NotStartsWith(field, prefix)` | 不以...开头 | -| `ENDS WITH` | `EndsWith(field, suffix)` | 以...结尾 | -| `NOT ENDS WITH` | `NotEndsWith(field, suffix)` | 不以...结尾 | -| `IS NULL` | `IsNull(field)` | 为空 | -| `IS NOT NULL` | `NotNull(field)` | 不为空 | - -### Object 和 Array 类型 - -SRDB 支持复杂的数据类型,可以存储 JSON 风格的对象和数组: - -```go -// 定义包含复杂类型的表 -type Article struct { - Title string `srdb:"field:title"` - Content string `srdb:"field:content"` - Tags []string `srdb:"field:tags"` // Array 类型 - Metadata map[string]any `srdb:"field:metadata"` // Object 类型 - Authors []string `srdb:"field:authors"` // Array 类型 -} - -// 使用 StructToFields 自动生成 Schema -fields, _ := srdb.StructToFields(Article{}) -schema, _ := srdb.NewSchema("articles", fields) -table, _ := db.CreateTable("articles", schema) - -// 插入数据 -table.Insert(map[string]any{ - "title": "SRDB 使用指南", - "content": "...", - "tags": []any{"database", "golang", "lsm-tree"}, - "metadata": map[string]any{ - "category": "tech", - "views": 1250, - "featured": true, - }, - "authors": []any{"Alice", "Bob"}, -}) - -// 查询和扫描 -var article Article -table.Query().Eq("title", "SRDB 使用指南").Scan(&article) - -fmt.Println(article.Tags) // ["database", "golang", "lsm-tree"] -fmt.Println(article.Metadata["category"]) // "tech" -fmt.Println(article.Metadata["views"]) // 1250 -``` - -**支持的场景**: -- ✅ `map[string]xxx` - 任意键值对 -- ✅ `struct{}` - 结构体(自动转换为 Object) -- ✅ `*struct{}` - 结构体指针 -- ✅ `[]xxx` - 任意类型的切片 -- ✅ 嵌套的 Object 和 Array -- ✅ 空对象 `{}` 和空数组 `[]` - -**存储细节**: -- Object 和 Array 使用 JSON 编码存储 -- 存储格式:`[length: uint32][JSON data]` -- 零值:Object 为 `{}`,Array 为 `[]` -- 支持任意嵌套深度 - ---- - -## 🌐 Web UI - -SRDB 提供了一个功能强大的 Web 管理界面。 - -### 启动 Web UI - -```bash -cd examples/webui - -# 基本启动 -go run main.go serve - -# 自定义配置 -go run main.go serve --db /path/to/database --port 3000 - -# 启用自动数据插入(演示模式) -go run main.go serve --auto-insert -``` - -访问:http://localhost:8080 - -### 功能特性 - -- **表管理** - 查看所有表及其 Schema -- **数据浏览** - 分页浏览表数据,支持列选择 -- **Manifest 查看** - 可视化 LSM-Tree 结构 -- **实时监控** - Compaction 状态和统计 -- **主题切换** - 深色/浅色主题 -- **响应式设计** - 完美适配移动设备 - -详细文档:[examples/webui/README.md](examples/webui/README.md) - ---- - -## 🏗️ 架构设计 - -### LSM-Tree 结构 +1. **内存层** - WAL(Write-Ahead Log)+ MemTable(Active + Immutable) +2. **磁盘层** - SST 文件(带 B+Tree 索引),分层存储(L0-L3) ``` 写入流程: - 数据 - ↓ - WAL(持久化) - ↓ - MemTable(内存) - ↓ - Immutable MemTable - ↓ - Level 0 SST(磁盘) - ↓ - Level 1-6 SST(Compaction) +数据 → WAL(持久化)→ MemTable → Flush → SST L0 → Compaction → SST L1-L3 + +读取流程: +查询 → MemTable(O(1))→ Immutable MemTables → SST Files(B+Tree) ``` -### 组件架构 +### 数据文件 ``` -Database -├── Table (Schema + Storage) -│ ├── MemTable Manager -│ │ ├── Active MemTable -│ │ └── Immutable MemTables -│ ├── SSTable Manager -│ │ └── SST Files (Level 0-6) -│ ├── WAL Manager -│ │ └── Write-Ahead Log -│ ├── Version Manager -│ │ └── MVCC Versions -│ └── Compaction Manager -│ ├── Picker(选择策略) -│ └── Worker(执行合并) -└── Query Builder - └── Expression Engine +database_dir/ +├── database.meta # 数据库元数据 +└── table_name/ # 每表一个目录 + ├── schema.json # 表 Schema 定义 + ├── MANIFEST-000001 # 表级版本控制 + ├── CURRENT # 当前 MANIFEST 指针 + ├── wal/ # WAL 子目录 + │ ├── 000001.wal # WAL 文件 + │ └── CURRENT # 当前 WAL 指针 + ├── sst/ # SST 子目录(L0-L3 层级文件) + │ └── 000001.sst # SST 文件(B+Tree + 数据) + └── idx/ # 索引子目录 + └── idx_email.sst # 二级索引文件 ``` -### 数据流 +### 设计特点 -**写入路径**: -``` -Insert → WAL → MemTable → Flush → SST Level 0 → Compaction → SST Level 1-6 -``` - -**读取路径**: -``` -Query → MemTable → Immutable MemTables → SST Files (Level 0-6) -``` - -**Compaction 触发**: -- Level 0:文件数量 ≥ 4 -- Level 1-6:总大小超过阈值 -- Score 计算:`size / max_size` 或 `file_count / max_files` - ---- - -## ⚡ 性能特点 - -### 写入性能 -- **顺序写入** - WAL 和 MemTable 顺序写入,性能极高 -- **批量刷盘** - MemTable 达到阈值后批量刷盘 -- **异步 Compaction** - 后台异步执行,不阻塞写入 - -### 读取性能 -- **内存优先** - 优先从 MemTable 读取 -- **Bloom Filter** - 快速判断 key 是否存在(TODO) -- **索引加速** - 索引字段快速定位 -- **按需加载** - 游标模式惰性加载,节省内存 - -### 空间优化 -- **Snappy 压缩** - SST 文件自动压缩 -- **增量合并** - Compaction 只合并必要的文件 -- **垃圾回收** - 自动清理过期版本 - -### 性能指标(参考) - -| 操作 | 性能 | -|------|------| -| 顺序写入 | ~100K ops/s | -| 随机写入 | ~50K ops/s | -| 点查询 | ~10K ops/s | -| 范围扫描 | ~1M rows/s | - -*注:实际性能取决于硬件配置和数据特征* - ---- - -## 🛠️ 开发指南 - -### 项目结构 - -``` -srdb/ -├── btree.go # B-Tree 索引实现 -├── compaction.go # Compaction 管理器 -├── database.go # 数据库管理 -├── errors.go # 错误定义和处理 -├── index.go # 索引管理 -├── index_btree.go # 索引 B+Tree -├── memtable.go # 内存表 -├── query.go # 查询构建器 -├── schema.go # Schema 定义 -├── sstable.go # SSTable 文件 -├── table.go # 表管理(含存储引擎) -├── version.go # 版本管理(MVCC) -├── wal.go # Write-Ahead Log -├── webui/ # Web UI -│ ├── webui.go # HTTP 服务器 -│ └── static/ # 前端资源 -└── examples/ # 示例程序 - └── webui/ # Web UI 工具 -``` - -### 运行测试 - -```bash -# 运行所有测试 -go test ./... - -# 运行特定测试 -go test -v -run TestTable - -# 性能测试 -go test -bench=. -benchmem -``` - -### 构建示例 - -```bash -# 构建 WebUI -cd examples/webui -go build -o webui main.go - -# 运行 -./webui serve --db ./data -``` +- **Append-Only** - 无原地更新,简化并发控制 +- **MemTable** - `map[int64][]byte + sorted slice`,O(1) 读写 +- **SST 文件** - 4KB 节点的 B+Tree,mmap 零拷贝访问 +- **二进制编码** - ROW1 格式,无压缩,优先查询性能 +- **Compaction** - 后台异步合并,按层级管理文件大小 --- ## 📚 文档 ### 核心文档 -- [设计文档](DESIGN.md) - 详细的架构设计和实现原理 -- [CLAUDE.md](CLAUDE.md) - 完整的开发者指南 -- [Nullable 指南](NULLABLE_GUIDE.md) - Nullable 字段使用说明 -- [API 文档](https://pkg.go.dev/code.tczkiot.com/wlw/srdb) - Go API 参考 -### 示例和教程 +- [DOCS.md](DOCS.md) - 完整 API 文档和使用指南 +- [CLAUDE.md](CLAUDE.md) - 开发者指南和架构详解 +- [NULLABLE_GUIDE.md](NULLABLE_GUIDE.md) - Nullable 字段使用说明 + +### 示例教程 + - [Scan 方法指南](examples/scan_demo/README.md) - 扫描到结构体,支持 Object 和 Array -- [WebUI 工具](examples/webui/README.md) - Web 管理界面使用指南 - [所有类型示例](examples/all_types/) - 21 种类型的完整示例 - [Nullable 示例](examples/nullable/) - Nullable 字段的使用 +- [WebUI 工具](examples/webui/README.md) - Web 管理界面 + +--- + +## 🛠️ 开发 + +### 运行测试 + +```bash +# 所有测试 +go test -v ./... + +# 单个测试 +go test -v -run TestTable + +# 性能测试 +go test -bench=. -benchmem +``` + +### 构建 WebUI + +```bash +cd examples/webui +go build -o webui main.go +./webui serve --db ./data +``` --- @@ -673,13 +233,12 @@ MIT License - 详见 [LICENSE](LICENSE) 文件 ## 🙏 致谢 -- [LevelDB](https://github.com/google/leveldb) - LSM-Tree 设计灵感 +- [LevelDB](https://github.com/google/leveldb) - 架构设计参考 - [RocksDB](https://github.com/facebook/rocksdb) - Compaction 策略参考 -- [Lit](https://lit.dev/) - Web Components 框架 --- -## 📧 联系方式 +## 📧 联系 - 项目主页:https://code.tczkiot.com/wlw/srdb - Issue 跟踪:https://code.tczkiot.com/wlw/srdb/issues