golang高性能列式内存存储与位图索引事务插件库column的使用

Golang高性能列式内存存储与位图索引事务插件库column的使用

column logo

列式内存存储与位图索引

这个包包含一个高性能、列式、内存存储引擎,支持快速查询、更新和迭代,具有零分配和位图索引功能。

主要特性

  • 优化的、缓存友好的列式数据布局,最小化缓存未命中
  • 优化查询时的零堆内存分配
  • 优化的批量更新/删除,事务中的更新大约需要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)
}

性能优化技巧

  1. 批量操作:尽量使用批量插入和批量更新
  2. 索引使用:为常用查询条件创建索引
  3. 列选择:查询时只选择需要的列
  4. 复用事务:复用事务对象减少开销
  5. 预分配:预先估计数据量并分配足够空间

适用场景

  • 实时分析系统
  • 游戏服务器状态管理
  • 金融交易系统
  • 需要快速过滤查询的任何应用

column库通过列式存储和位图索引提供了极高的查询性能,特别适合需要处理大量数据并频繁执行过滤查询的场景。

回到顶部