golang高性能列式内存存储与位图索引事务插件库column的使用
Golang高性能列式内存存储与位图索引事务插件库column的使用
列式内存存储与位图索引
这个包包含一个高性能、列式、内存存储引擎,支持快速查询、更新和迭代,具有零分配和位图索引功能。
主要特性
- 优化的、缓存友好的列式数据布局,最小化缓存未命中
- 优化查询时的零堆内存分配
- 优化的批量更新/删除,事务中的更新大约需要
12ns
- 支持SIMD加速的聚合函数如"sum"、“avg”、“min"和"max”
- 支持SIMD加速的过滤(即"where"子句)
- 支持列式投影(即"select"子句)实现快速检索
- 支持计算索引,基于提供的谓词动态计算
- 支持并发更新
- 支持事务隔离
- 支持基于TTL或过期列的数据过期
- 支持原子合并任何值
- 支持主键
- 支持变更数据流
- 支持并发快照
完整示例
创建集合和列
// 创建新集合和一些列
players := column.NewCollection()
players.CreateColumn("name", column.ForString())
players.CreateColumn("class", column.ForString())
players.CreateColumn("balance", column.ForFloat64())
players.CreateColumn("age", column.ForInt16())
// 插入单条记录
index, err := players.Insert(func(r column.Row) error {
r.SetString("name", "merlin")
r.SetString("class", "mage")
r.SetFloat64("balance", 99.95)
r.SetInt16("age", 107)
return nil
})
// 批量插入记录
players.Query(func(txn *column.Txn) error {
for _, v := range myRawData {
txn.Insert(func(r column.Row) error {
// 设置各列值
return nil
})
}
return nil // 提交
})
查询和索引
// 创建"rogue"索引
players.CreateIndex("rogue", "class", func(v interface{}) bool {
return v == "rogue"
})
// 查询所有rogue
players.Query(func(txn *column.Txn) error {
count := txn.With("rogue").Count()
return nil
})
// 查询rogue和mage
players.Query(func(txn *column.Txn) error {
txn.With("rogue").Union("mage").Count()
return nil
})
// 查询非rogue
players.Query(func(txn *column.Txn) error {
txn.Without("rogue").Count()
return nil
})
// 查询年龄大于30的rogue
players.Query(func(txn *column.Txn) error {
txn.With("rogue").WithFloat("age", func(v float64) bool {
return v >= 30
}).Count()
return nil
})
迭代结果
// 迭代所有rogue并打印名字
players.Query(func(txn *column.Txn) error {
names := txn.String("name") // 创建列读取器
return txn.With("rogue").Range(func(i uint32) {
name, _ := names.Get()
println("rogue name", name)
})
})
// 迭代并获取多个列
players.Query(func(txn *column.Txn) error {
names := txn.String("name")
ages := txn.Int64("age")
return txn.With("rogue").Range(func(i uint32) {
name, _ := names.Get()
age, _ := ages.Get()
println("rogue name", name)
println("rogue age", age)
})
})
更新值
// 更新所有rogue的balance和age
players.Query(func(txn *column.Txn) error {
balance := txn.Float64("balance")
age := txn.Int64("age")
return txn.With("rogue").Range(func(i uint32) {
balance.Set(10.0) // 设置"balance"为10.0
age.Set(50) // 设置"age"为50
})
})
// 原子增加rogue的balance
players.Query(func(txn *column.Txn) error {
balance := txn.Float64("balance")
return txn.With("rogue").Range(func(i uint32) {
balance.Merge(500.0) // "balance"增加500
})
})
使用主键
players := column.NewCollection()
players.CreateColumn("name", column.ForKey()) // 创建"name"作为主键
players.CreateColumn("class", column.ForString()) // 其他列
// 插入主键为"merlin"的玩家
players.InsertKey("merlin", func(r column.Row) error {
r.SetString("class", "mage")
return nil
})
// 查询主键为"merlin"的玩家
players.QueryKey("merlin", func(r column.Row) error {
class, _ := r.String("class")
return nil
})
存储二进制记录
type Location struct {
X float64 `json:"x"`
Y float64 `json:"y"`
}
func (l Location) MarshalBinary() ([]byte, error) {
return json.Marshal(l)
}
func (l *Location) UnmarshalBinary(b []byte) error {
return json.Unmarshal(b, l)
}
// 创建位置列
players.CreateColumn("location", ForRecord(func() *Location {
return new(Location)
}))
// 插入位置记录
idx, _ := players.Insert(func(r Row) error {
r.SetRecord("location", &Location{X: 1, Y: 2})
return nil
})
// 读取位置记录
players.QueryAt(idx, func(r Row) error {
location, ok := r.Record("location")
return nil
})
性能基准
在包含12列的100,000项集合上运行的基准测试:
cpu: Intel(R) Core(TM) i7-9700K CPU @ 3.60GHz
BenchmarkCollection/insert-8 2523 469481 ns/op 24356 B/op 500 allocs/op
BenchmarkCollection/select-at-8 22194190 54.23 ns/op 0 B/op 0 allocs/op
BenchmarkCollection/scan-8 2068 568953 ns/op 122 B/op 0 allocs/op
BenchmarkCollection/count-8 571449 2057 ns/op 0 B/op 0 allocs/op
BenchmarkCollection/range-8 28660 41695 ns/op 3 B/op 0 allocs/op
BenchmarkCollection/update-at-8 5911978 202.8 ns/op 0 B/op 0 allocs/op
BenchmarkCollection/update-all-8 1280 946272 ns/op 3726 B/op 0 allocs/op
BenchmarkCollection/delete-at-8 6405852 188.9 ns/op 0 B/op 0 allocs/op
BenchmarkCollection/delete-all-8 2073188 562.6 ns/op 0 B/op 0 allocs/op
许可证
Tile基于MIT许可证授权。
更多关于golang高性能列式内存存储与位图索引事务插件库column的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复
更多关于golang高性能列式内存存储与位图索引事务插件库column的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
Golang高性能列式内存存储与位图索引事务插件库column使用指南
column库简介
column是一个Go语言实现的高性能列式内存存储引擎,支持位图索引和事务操作。它特别适合需要快速查询和分析大量数据的场景。
核心特性
- 列式存储:数据按列而非按行存储,提高分析查询性能
- 位图索引:高效压缩的位图索引,加速过滤查询
- 事务支持:ACID事务保证数据一致性
- 内存存储:所有操作在内存中完成,极高性能
安装
go get github.com/kelindar/column
基本使用示例
1. 创建集合
package main
import (
"fmt"
"github.com/kelindar/column"
)
func main() {
// 创建一个新的集合
players := column.NewCollection()
// 定义列结构
players.CreateColumn("name", column.ForString())
players.CreateColumn("age", column.ForInt())
players.CreateColumn("score", column.ForFloat64())
players.CreateColumn("active", column.ForBool())
}
2. 插入数据
// 插入单条记录
players.Insert(func(r column.Row) error {
r.SetString("name", "Alice")
r.SetInt("age", 28)
r.SetFloat64("score", 95.5)
r.SetBool("active", true)
return nil
})
// 批量插入数据
for i := 0; i < 1000; i++ {
players.Insert(func(r column.Row) error {
r.SetString("name", fmt.Sprintf("Player%d", i))
r.SetInt("age", 20 + i%30)
r.SetFloat64("score", float64(50 + i%50))
r.SetBool("active", i%2 == 0)
return nil
})
}
3. 查询数据
// 简单查询
players.Query(func(txn *column.Txn) error {
return txn.Range(func(i uint32) {
name, _ := txn.String("name", i)
age, _ := txn.Int("age", i)
fmt.Printf("Player %d: %s, age %d\n", i, name, age)
})
})
// 带条件的查询
players.Query(func(txn *column.Txn) error {
return txn.With("active").Range(func(i uint32) {
name, _ := txn.String("name", i)
score, _ := txn.Float64("score", i)
fmt.Printf("Active player: %s, score %.1f\n", name, score)
})
})
4. 使用位图索引
// 创建索引
players.CreateIndex("active_idx", "active")
// 使用索引查询
players.Query(func(txn *column.Txn) error {
return txn.With("active_idx").Range(func(i uint32) {
name, _ := txn.String("name", i)
fmt.Println("Active player:", name)
})
})
5. 更新数据
players.Query(func(txn *column.Txn) error {
return txn.WithInt("age", func(v int64) bool {
return v > 40 // 只更新年龄大于40的记录
}).Update(func(r column.Row) error {
score, _ := r.Float64("score")
r.SetFloat64("score", score * 1.1) // 给老玩家10%分数加成
return nil
})
})
6. 删除数据
players.Query(func(txn *column.Txn) error {
return txn.WithFloat64("score", func(v float64) bool {
return v < 60 // 删除分数低于60的记录
}).Delete()
})
7. 事务操作
err := players.Update(func(txn *column.Txn) error {
// 开始事务
if err := txn.Range(func(i uint32) {
// 检查条件
active, _ := txn.Bool("active", i)
if !active {
return
}
// 更新数据
score, _ := txn.Float64("score", i)
txn.SetFloat64("score", i, score+5.0) // 给活跃玩家加5分
}); err != nil {
return err
}
return nil
})
if err != nil {
fmt.Println("Transaction failed:", err)
}
性能优化技巧
- 批量操作:尽量使用批量插入和批量更新
- 索引使用:为常用查询条件创建索引
- 列选择:查询时只选择需要的列
- 复用事务:复用事务对象减少开销
- 预分配:预先估计数据量并分配足够空间
适用场景
- 实时分析系统
- 游戏服务器状态管理
- 金融交易系统
- 需要快速过滤查询的任何应用
column库通过列式存储和位图索引提供了极高的查询性能,特别适合需要处理大量数据并频繁执行过滤查询的场景。