第5章-添加操作
让我们通过一个完整的示例来演示 sfsDb 的添加操作:5.2 Insert 方法方法用于插入单条记录到表中。函数签名(来自 ):参数说明:返回值:5.3 BatchInsertInc 方法方法用于批量插入记录,支持自动递增 ID。函数签名(来自 ):参数说明:返回值:5.4 BatchInsertNoInc 方法方法用于批量插入记录,不自动递增 ID(使用用户提供的 ID)。函数签名(来自 ):
·
第 5 章:添加操作
5.1 完整的可运行示例
让我们通过一个完整的示例来演示 sfsDb 的添加操作:
package main
import (
"fmt"
"os"
"github.com/liaoran123/sfsDb/engine"
"github.com/liaoran123/sfsDb/storage"
)
func main() {
fmt.Println("=== sfsDb 数据库实战 - 第 4 章:添加操作示例 ===")
fmt.Println()
dbPath := "./bible_examples_chapter04_db"
cleanup(dbPath)
fmt.Println("1. 初始化数据库")
_, err := storage.GetDBManager().OpenDB(dbPath)
if err != nil {
fmt.Printf("数据库打开失败: %v\n", err)
return
}
defer storage.GetDBManager().CloseDB()
fmt.Println(" ✓ 数据库打开成功")
fmt.Println()
fmt.Println("2. 创建表并设置字段")
table, err := engine.NewTable("users")
if err != nil {
fmt.Printf("创建表失败: %v\n", err)
return
}
fields := map[string]any{
"id": 0,
"name": "",
"email": "",
"age": 0,
}
err = table.SetFields(fields)
if err != nil {
fmt.Printf("设置字段失败: %v\n", err)
return
}
primaryKey, err := engine.NewDefaultPrimaryKey("pk_id")
primaryKey.AddFields("id")
table.CreateIndex(primaryKey)
fmt.Println(" ✓ 表创建成功")
fmt.Println()
fmt.Println("3. 单个插入操作 (Insert)")
user1 := map[string]any{"id": 1, "name": "张三", "email": "zhangsan@example.com", "age": 28}
id1, err := table.Insert(&user1)
if err != nil {
fmt.Printf("插入数据失败: %v\n", err)
return
}
fmt.Printf(" ✓ 成功插入用户,ID: %d\n", id1)
fmt.Println()
fmt.Println("4. 批量插入操作 (BatchInsertInc)")
users := []*map[string]any{
{"id": 2, "name": "李四", "email": "lisi@example.com", "age": 32},
{"id": 3, "name": "王五", "email": "wangwu@example.com", "age": 25},
{"id": 4, "name": "赵六", "email": "zhaoliu@example.com", "age": 35},
}
ids, err := table.BatchInsertInc(users)
if err != nil {
fmt.Printf("批量插入失败: %v\n", err)
return
}
fmt.Printf(" ✓ 成功批量插入 %d 个用户,IDs: %v\n", len(ids), ids)
fmt.Println()
fmt.Println("5. 批量插入操作 (BatchInsertNoInc)")
usersNoInc := []*map[string]any{
{"id": 5, "name": "孙七", "email": "sunqi@example.com", "age": 29},
{"id": 6, "name": "周八", "email": "zhouba@example.com", "age": 31},
}
idsNoInc, err := table.BatchInsertNoInc(usersNoInc)
if err != nil {
fmt.Printf("批量插入失败: %v\n", err)
return
}
fmt.Printf(" ✓ 成功批量插入 %d 个用户,IDs: %v\n", len(idsNoInc), idsNoInc)
fmt.Println()
fmt.Println("6. 验证所有数据")
searchAll := map[string]any{"id": nil}
dataIter, _ := table.Search(&searchAll)
defer dataIter.Release()
records := dataIter.GetRecords(true)
defer records.Release()
fmt.Println(" 所有用户列表:")
for _, user := range records {
fmt.Printf(" - ID: %v, 姓名: %v, 邮箱: %v, 年龄: %v\n",
user["id"], user["name"], user["email"], user["age"])
}
fmt.Println()
fmt.Println("=== 添加操作演示完成!===")
}
func cleanup(path string) {
os.RemoveAll(path)
}
5.2 Insert 方法
Insert 方法用于插入单条记录到表中。
函数签名(来自 engine/tableInsert.go):
func (t *Table) Insert(fields *map[string]any, batchs ...storage.Batch) (currentID int, err error) {
// 实现代码...
}
参数说明:
fields:要插入的字段映射batchs:可选的批处理对象
返回值:
currentID:插入记录的 IDerr:错误信息
使用示例
// 插入单条记录
user := map[string]any{"id": 1, "name": "张三", "email": "zhangsan@example.com"}
id, err := table.Insert(&user)
if err != nil {
fmt.Printf("插入失败: %v\n", err)
} else {
fmt.Printf("插入成功,ID: %d\n", id)
}
5.3 BatchInsertInc 方法
BatchInsertInc 方法用于批量插入记录,支持自动递增 ID。
函数签名(来自 engine/tableInsert.go):
func (t *Table) BatchInsertInc(records []*map[string]any, batchs ...storage.Batch) ([]int, error) {
// 实现代码...
}
参数说明:
records:要插入的记录数组batchs:可选的批处理对象
返回值:
[]int:插入记录的 ID 数组error:错误信息
使用示例
// 批量插入记录
users := []*map[string]any{
{"name": "李四", "email": "lisi@example.com"},
{"name": "王五", "email": "wangwu@example.com"},
}
ids, err := table.BatchInsertInc(users)
if err != nil {
fmt.Printf("批量插入失败: %v\n", err)
} else {
fmt.Printf("批量插入成功,IDs: %v\n", ids)
}
5.4 BatchInsertNoInc 方法
BatchInsertNoInc 方法用于批量插入记录,不自动递增 ID(使用用户提供的 ID)。
函数签名(来自 engine/tableInsert.go):
func (t *Table) BatchInsertNoInc(records []*map[string]any, batchs ...storage.Batch) ([]int, error) {
// 实现代码...
}
参数说明:
records:要插入的记录数组(必须包含 ID 字段)batchs:可选的批处理对象
返回值:
[]int:插入记录的 ID 数组error:错误信息
使用示例
// 批量插入记录(使用指定的 ID)
users := []*map[string]any{
{"id": 101, "name": "孙七", "email": "sunqi@example.com"},
{"id": 102, "name": "周八", "email": "zhouba@example.com"},
}
ids, err := table.BatchInsertNoInc(users)
if err != nil {
fmt.Printf("批量插入失败: %v\n", err)
} else {
fmt.Printf("批量插入成功,IDs: %v\n", ids)
}
5.5 插入操作的内部实现
5.5.1 核心流程
- 参数验证:检查表是否初始化、字段是否设置
- ID 处理:处理自动递增 ID 或使用用户提供的 ID
- 数据编码:将字段数据编码为二进制格式
- 索引处理:更新主键索引和其他索引
- 数据存储:将数据存储到 KV 存储中
- 批量处理:支持批处理操作以提高性能
5.5.2 关键代码
ID 生成逻辑:
// 生成 ID
if (*fields)[t.PrimaryKeyName] == nil {
// 自动递增 ID
currentID = t.currentID
t.currentID++
} else {
// 使用用户提供的 ID
currentID = (*fields)[t.PrimaryKeyName].(int)
if currentID >= t.currentID {
t.currentID = currentID + 1
}
}
数据编码:
// 编码数据
value, err := t.encodeFields(*fields)
if err != nil {
return 0, err
}
// 生成键
key := index.JoinFullValues(fieldsBytes, currentID)
defer key.Release()
5.6 插入操作的最佳实践
- 批量插入:对于大量数据,使用
BatchInsertInc或BatchInsertNoInc以提高性能 - ID 管理:根据业务需求选择自动递增 ID 或自定义 ID
- 错误处理:始终检查插入操作的错误返回
- 事务处理:对于重要操作,考虑使用事务确保数据一致性
- 数据验证:在插入前验证数据的有效性
5.7 性能优化
- 批处理:使用批处理减少数据库交互次数
- 预分配:预分配切片空间以减少内存分配
- 索引设计:合理设计索引以提高插入性能
- 并发插入:在适当情况下使用并发插入
5.8 小结
本章我们通过项目的实际代码学习了 sfsDb 的添加操作:
- 单条插入:使用
Insert方法插入单条记录 - 批量插入:使用
BatchInsertInc和BatchInsertNoInc方法批量插入记录 - ID 管理:支持自动递增 ID 和自定义 ID
- 批处理支持:支持批处理操作以提高性能
- 内部实现:了解插入操作的核心流程和关键代码
- 最佳实践:掌握插入操作的最佳实践和性能优化技巧
在下一章中,我们将学习删除操作。
本书版本:6.0.0
最后更新:2026-03-16
sfsDb - 以工业物联网边缘计算为核心场景的高性能嵌入式数据库!🚀
技术栈 - Go、leveldb。纯golang实现。
项目地址:GitHub
GitCode 镜像:GitCode
更多推荐
所有评论(0)