作为一名C#开发者,你是否在项目中遇到过这样的痛点:需要频繁查询配置数据、游戏数据或者静态资源数据,但传统数据库的性能瓶颈让应用卡顿不已?今天要为大家介绍的MasterMemory,正是为解决这一问题而生的革命性方案。
这个由Cysharp团队开发的开源项目,不仅在性能上碾压传统方案(比SQLite快4700倍!有点吹牛逼),更在类型安全和易用性上做到了极致。本文将深入解析MasterMemory的核心特性,并提供实战代码示例,让你快速掌握这个强大的内存数据库工具。
传统的SQLite在处理频繁查询时,每次查询都需要进行文件I/O操作,在高并发场景下性能急剧下降。特别是在游戏开发、配置管理等需要大量读取操作的场景中,这种性能损耗是致命的。
使用传统数据库时,SQL查询是字符串形式,编译期无法检查错误,只有在运行时才能发现问题。这不仅增加了调试难度,也容易引入生产环境的bug。
传统方案往往需要额外的ORM层,加上数据库引擎本身的开销,内存占用居高不下。对于嵌入式应用或移动端开发,这是个严重问题。
通过Source Generator技术,在编译期自动生成强类型API,彻底告别字符串拼接的查询方式。
完美支持.NET和Unity,满足桌面应用、移动应用、游戏开发等多种场景需求。
支持主键查询、多键组合查询、范围查询、最近值查询等多种查询方式。
Bash# NuGet包管理器
Install-Package MasterMemory
# .NET CLI
dotnet add package MasterMemory
C#public enum Gender
{
Male, Female, Unknown
}
// 使用MemoryTable标记表定义
[MemoryTable("person"), MessagePackObject(true)]
public record Person
{
// 主键定义
[PrimaryKey]
public required int PersonId { get; init; }
// 多重索引定义
[SecondaryKey(0), NonUnique]
[SecondaryKey(1, keyOrder: 1), NonUnique]
public required int Age { get; init; }
[SecondaryKey(2), NonUnique]
[SecondaryKey(1, keyOrder: 0), NonUnique]
public required Gender Gender { get; init; }
public required string Name { get; init; }
}
💡 关键要点:
record类型确保数据不可变性MessagePackObject(true)启用高性能序列化SecondaryKey支持复杂查询场景C#// 创建数据库构建器
var builder = new DatabaseBuilder();
// 添加测试数据
builder.Append(new Person[]
{
new() { PersonId = 0, Age = 13, Gender = Gender.Male, Name = "Dana Terry" },
new() { PersonId = 1, Age = 17, Gender = Gender.Male, Name = "Kirk Obrien" },
new() { PersonId = 2, Age = 31, Gender = Gender.Male, Name = "Wm Banks" },
new() { PersonId = 3, Age = 44, Gender = Gender.Male, Name = "Karl Benson" },
new() { PersonId = 4, Age = 23, Gender = Gender.Male, Name = "Jared Holland" },
new() { PersonId = 5, Age = 27, Gender = Gender.Female, Name = "Jeanne Phelps" },
// ... 更多数据
});
// 构建数据库二进制数据
byte[] databaseBinary = builder.Build();
// 也可以直接保存到文件
using var fileStream = File.Create("database.bin");
builder.WriteToStream(fileStream);
⚠️ 注意事项:
C#// 创建数据库实例(建议单例模式)
var database = new MemoryDatabase(databaseBinary);
// 主键查询 - 最快速度
Person person = database.PersonTable.FindByPersonId(5);
Console.WriteLine($"Found: {person.Name}"); // "Jeanne Phelps"
// 复合索引查询 - 智能类型推断
RangeView<Person> femaleAge27 = database.PersonTable
.FindByGenderAndAge((Gender.Female, 27));
// 范围查询 - 灵活筛选
RangeView<Person> ageRange = database.PersonTable
.FindRangeByAge(20, 30); // 20-30岁之间
// 最近值查询 - 智能匹配
RangeView<Person> closestAge = database.PersonTable
.FindClosestByAge(25); // 找到最接近25岁的记录
// 安全查询 - 避免异常
if (database.PersonTable.TryFindByPersonId(999, out Person result))
{
Console.WriteLine($"找到用户: {result.Name}");
}
else
{
Console.WriteLine("用户不存在");
}

🎯 性能优化技巧:
RangeView<T>避免不必要的内存分配TryFind方法避免异常处理开销C#// 使用ImmutableBuilder进行数据更新
var builder = database.ToImmutableBuilder();
// 添加或替换数据(基于主键)
builder.Diff(new Person[]
{
new() { PersonId = 10, Age = 25, Gender = Gender.Female, Name = "New User" }
});
// 删除指定数据
builder.RemovePerson(new[] { 1, 2, 3 });
// 生成新的数据库实例
MemoryDatabase newDatabase = builder.Build();
C#[MemoryTable("quest"), MessagePackObject(true)]
public class Quest : IValidatable<Quest>
{
[PrimaryKey]
public int QuestId { get; init; }
public string Name { get; init; }
public int RewardItemId { get; init; }
public int RequiredLevel { get; init; }
void IValidatable<Quest>.Validate(IValidator<Quest> validator)
{
// 获取外部引用表
var items = validator.GetReferenceSet<Item>();
// 验证外键关系
if (RewardItemId > 0)
{
items.Exists(x => x.RewardItemId, x => x.ItemId);
}
// 范围验证
validator.Validate(x => x.RequiredLevel >= 1 && x.RequiredLevel <= 100);
// 全局唯一性验证
if (validator.CallOnce())
{
var quests = validator.GetTableSet();
quests.Where(x => x.RewardItemId > 0)
.Unique(x => x.RewardItemId);
}
}
}
// 执行验证
var validateResult = database.Validate();
if (validateResult.IsValidationFailed)
{
Console.WriteLine(validateResult.FormatFailedResults());
}
C#
using MasterMemory;
using MessagePack;
using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
namespace AppMasterMemory
{
// 定义枚举
public enum Gender
{
Male,
Female,
Unknown
}
// 定义数据模型
[MemoryTable("person"), MessagePackObject(true)]
public record Person
{
// 主键定义
[PrimaryKey]
public required int PersonId { get; init; }
// 多重索引定义
[SecondaryKey(0), NonUnique]
[SecondaryKey(1, keyOrder: 1), NonUnique]
public required int Age { get; init; }
[SecondaryKey(2), NonUnique]
[SecondaryKey(1, keyOrder: 0), NonUnique]
public required Gender Gender { get; init; }
public required string Name { get; init; }
}
class Program
{
static void Main(string[] args)
{
Console.OutputEncoding = System.Text.Encoding.UTF8;
Console.WriteLine("🚀 MasterMemory 内存数据库示例");
Console.WriteLine("================================\n");
// 第一步:创建初始数据库
var initialDatabase = CreateInitialDatabase();
// 第二步:演示各种查询操作
DemonstrateQueries(initialDatabase);
// 第三步:演示数据更新操作
var updatedDatabase = DemonstrateDataUpdates(initialDatabase);
// 第四步:演示批量操作
DemonstrateBatchOperations(updatedDatabase);
Console.WriteLine("\n✅ 示例执行完成!");
Console.ReadKey();
}
/// <summary>
/// 创建初始数据库
/// </summary>
static MemoryDatabase CreateInitialDatabase()
{
Console.WriteLine("📦 创建初始数据库...");
// 创建数据库构建器
var builder = new DatabaseBuilder();
// 添加测试数据
builder.Append(new Person[]
{
new() { PersonId = 0, Age = 13, Gender = Gender.Male, Name = "Dana Terry" },
new() { PersonId = 1, Age = 17, Gender = Gender.Male, Name = "Kirk Obrien" },
new() { PersonId = 2, Age = 31, Gender = Gender.Male, Name = "Wm Banks" },
new() { PersonId = 3, Age = 44, Gender = Gender.Male, Name = "Karl Benson" },
new() { PersonId = 4, Age = 23, Gender = Gender.Male, Name = "Jared Holland" },
new() { PersonId = 5, Age = 27, Gender = Gender.Female, Name = "Jeanne Phelps" },
new() { PersonId = 6, Age = 25, Gender = Gender.Female, Name = "Alice Johnson" },
new() { PersonId = 7, Age = 35, Gender = Gender.Male, Name = "Bob Smith" },
new() { PersonId = 8, Age = 22, Gender = Gender.Female, Name = "Carol Wilson" },
new() { PersonId = 9, Age = 28, Gender = Gender.Male, Name = "David Brown" }
});
// 构建数据库
byte[] databaseBinary = builder.Build();
var database = new MemoryDatabase(databaseBinary);
Console.WriteLine($"✅ 数据库创建成功!共 {database.PersonTable.All.Count()} 条记录\n");
return database;
}
/// <summary>
/// 演示各种查询操作
/// </summary>
static void DemonstrateQueries(MemoryDatabase database)
{
Console.WriteLine("🔍 查询操作演示");
Console.WriteLine("----------------");
// 1. 主键查询 - 最快速度
Console.WriteLine("1. 主键查询:");
var person = database.PersonTable.FindByPersonId(5);
Console.WriteLine($" ID=5 的用户: {person.Name}, 年龄: {person.Age}, 性别: {person.Gender}");
// 2. 复合索引查询
Console.WriteLine("\n2. 复合索引查询(性别+年龄):");
var femaleAge27 = database.PersonTable.FindByGenderAndAge((Gender.Female, 27));
foreach (var p in femaleAge27)
{
Console.WriteLine($" 女性,27岁: {p.Name}");
}
// 3. 范围查询
Console.WriteLine("\n3. 年龄范围查询(20-30岁):");
var ageRange = database.PersonTable.FindRangeByAge(20, 30);
foreach (var p in ageRange)
{
Console.WriteLine($" {p.Name}: {p.Age}岁");
}
// 4. 性别分组查询
Console.WriteLine("\n4. 按性别查询:");
var females = database.PersonTable.FindByGender(Gender.Female);
Console.WriteLine($" 女性用户数量: {females.Count()}");
foreach (var p in females)
{
Console.WriteLine($" - {p.Name}, {p.Age}岁");
}
// 5. 安全查询 - 避免异常
Console.WriteLine("\n5. 安全查询(用户不存在的情况):");
if (database.PersonTable.TryFindByPersonId(999, out Person result))
{
Console.WriteLine($" 找到用户: {result.Name}");
}
else
{
Console.WriteLine(" 用户ID=999不存在");
}
// 6. LINQ查询
Console.WriteLine("\n6. LINQ复杂查询(年龄>25的男性,按年龄排序):");
var complexQuery = database.PersonTable.All
.Where(p => p.Gender == Gender.Male && p.Age > 25)
.OrderBy(p => p.Age);
foreach (var p in complexQuery)
{
Console.WriteLine($" {p.Name}: {p.Age}岁");
}
Console.WriteLine();
}
/// <summary>
/// 演示数据更新操作
/// </summary>
static MemoryDatabase DemonstrateDataUpdates(MemoryDatabase database)
{
Console.WriteLine("🛠️ 数据更新操作演示");
Console.WriteLine("--------------------");
// 使用ImmutableBuilder进行数据更新
var builder = database.ToImmutableBuilder();
Console.WriteLine("1. 添加新用户:");
// 添加或替换数据(基于主键)
var newUsers = new Person[]
{
new() { PersonId = 10, Age = 25, Gender = Gender.Female, Name = "New User" },
new() { PersonId = 11, Age = 30, Gender = Gender.Male, Name = "Another User" },
new() { PersonId = 12, Age = 26, Gender = Gender.Female, Name = "Third User" }
};
builder.Diff(newUsers);
foreach (var user in newUsers)
{
Console.WriteLine($" 添加: {user.Name}, {user.Age}岁, {user.Gender}");
}
Console.WriteLine("\n2. 删除指定用户:");
var idsToRemove = new[] { 1, 2, 3 };
// 在删除前显示要删除的用户信息
foreach (var id in idsToRemove)
{
if (database.PersonTable.TryFindByPersonId(id, out var userToDelete))
{
Console.WriteLine($" 删除: {userToDelete.Name} (ID={id})");
}
}
builder.RemovePerson(idsToRemove);
// 生成新的数据库实例
MemoryDatabase newDatabase = builder.Build();
Console.WriteLine($"\n✅ 更新完成!原数据库: {database.PersonTable.All.Count()} 条记录");
Console.WriteLine($" 新数据库: {newDatabase.PersonTable.All.Count()} 条记录\n");
return newDatabase;
}
/// <summary>
/// 演示批量操作
/// </summary>
static void DemonstrateBatchOperations(MemoryDatabase database)
{
Console.WriteLine("📊 批量操作演示");
Console.WriteLine("----------------");
// 统计信息
var allPersons = database.PersonTable.All.ToList();
var totalCount = allPersons.Count;
var maleCount = allPersons.Count(p => p.Gender == Gender.Male);
var femaleCount = allPersons.Count(p => p.Gender == Gender.Female);
var avgAge = allPersons.Average(p => p.Age);
Console.WriteLine("1. 数据统计:");
Console.WriteLine($" 总用户数: {totalCount}");
Console.WriteLine($" 男性用户: {maleCount}");
Console.WriteLine($" 女性用户: {femaleCount}");
Console.WriteLine($" 平均年龄: {avgAge:F1}岁");
// 年龄分组统计
Console.WriteLine("\n2. 年龄分组统计:");
var ageGroups = allPersons
.GroupBy(p => p.Age / 10 * 10) // 按十年分组
.OrderBy(g => g.Key);
foreach (var group in ageGroups)
{
Console.WriteLine($" {group.Key}-{group.Key + 9}岁: {group.Count()}人");
}
// 姓名长度统计
Console.WriteLine("\n3. 姓名长度分析:");
var nameLengths = allPersons
.GroupBy(p => p.Name.Length)
.OrderBy(g => g.Key);
foreach (var group in nameLengths)
{
Console.WriteLine($" {group.Key}个字符: {group.Count()}人");
}
// 查找特定条件的用户
Console.WriteLine("\n4. 条件查找:");
var youngAdults = allPersons
.Where(p => p.Age >= 20 && p.Age <= 30)
.OrderBy(p => p.Age)
.ToList();
Console.WriteLine($" 20-30岁的用户 ({youngAdults.Count}人):");
foreach (var person in youngAdults.Take(5)) // 只显示前5个
{
Console.WriteLine($" - {person.Name}, {person.Age}岁, {person.Gender}");
}
if (youngAdults.Count > 5)
{
Console.WriteLine($" ... 还有 {youngAdults.Count - 5} 人");
}
}
}
/// <summary>
/// 实际应用示例:用户管理服务
/// </summary>
public class UserManagementService
{
private MemoryDatabase _database;
public UserManagementService(MemoryDatabase database)
{
_database = database;
}
/// <summary>
/// 根据年龄范围获取用户
/// </summary>
public IEnumerable<Person> GetUsersByAgeRange(int minAge, int maxAge)
{
return _database.PersonTable.FindRangeByAge(minAge, maxAge);
}
/// <summary>
/// 获取指定性别的用户
/// </summary>
public IEnumerable<Person> GetUsersByGender(Gender gender)
{
return _database.PersonTable.FindByGender(gender);
}
/// <summary>
/// 搜索用户(按姓名模糊匹配)
/// </summary>
public IEnumerable<Person> SearchUsersByName(string namePattern)
{
return _database.PersonTable.All
.Where(p => p.Name.Contains(namePattern, StringComparison.OrdinalIgnoreCase));
}
/// <summary>
/// 获取用户统计信息
/// </summary>
public UserStatistics GetStatistics()
{
var allUsers = _database.PersonTable.All.ToList();
return new UserStatistics
{
TotalUsers = allUsers.Count,
MaleUsers = allUsers.Count(p => p.Gender == Gender.Male),
FemaleUsers = allUsers.Count(p => p.Gender == Gender.Female),
AverageAge = allUsers.Average(p => p.Age),
MinAge = allUsers.Min(p => p.Age),
MaxAge = allUsers.Max(p => p.Age)
};
}
/// <summary>
/// 批量更新数据库
/// </summary>
public MemoryDatabase UpdateDatabase(
IEnumerable<Person> usersToAdd,
IEnumerable<int> userIdsToRemove)
{
var builder = _database.ToImmutableBuilder();
if (usersToAdd?.Any() == true)
{
builder.Diff(usersToAdd.ToArray());
}
if (userIdsToRemove?.Any() == true)
{
builder.RemovePerson(userIdsToRemove.ToArray());
}
return builder.Build();
}
}
/// <summary>
/// 用户统计信息
/// </summary>
public record UserStatistics
{
public int TotalUsers { get; init; }
public int MaleUsers { get; init; }
public int FemaleUsers { get; init; }
public double AverageAge { get; init; }
public int MinAge { get; init; }
public int MaxAge { get; init; }
}
}

C#// 利用多核CPU加速数据库构建
var database = new MemoryDatabase(
databaseBinary,
maxDegreeOfParallelism: Environment.ProcessorCount
);
C#// 禁用字符串驻留(适用于唯一字符串较多的场景)
var database = new MemoryDatabase(databaseBinary, internString: false);
// 自定义MessagePack解析器
var database = new MemoryDatabase(
databaseBinary,
formatterResolver: CustomResolver.Instance
);
C#// 在项目文件中定义条件编译符号来减少生成代码大小
#if !DEBUG
#define DISABLE_MASTERMEMORY_VALIDATOR
#define DISABLE_MASTERMEMORY_METADATABASE
#endif
C#// 使用Key特性替代自动序列化,获得更好的性能
[MemoryTable("optimized_person"), MessagePackObject]
public record OptimizedPerson
{
[Key(0), PrimaryKey]
public int PersonId { get; init; }
[Key(1)]
public string Name { get; init; }
[Key(2), SecondaryKey(0)]
public int Age { get; init; }
}
通过本文的深入解析,我们可以看出MasterMemory作为一个革命性的内存数据库方案,在性能、类型安全、易用性三个维度都达到了行业领先水平。
MasterMemory不仅仅是一个技术工具,更代表了现代C#开发中对性能和开发体验的极致追求。无论你是游戏开发者、企业应用开发者还是性能优化专家,这个强大的工具都值得加入你的技术栈。
🤔 互动讨论:
觉得这篇文章对你有帮助吗?请点赞并转发给更多需要的同行!让我们一起推动C#技术社区的发展! 💪
关注我,获取更多C#开发实战技巧和最新技术动态!
本文作者:技术老小子
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!