我希望能够在数据存储中运行一组记录/文档,但始终让这些记录在 RAM 中保持新鲜。我只需要使用大约 1.5GB 到 2GB 的 RAM(可能更少)。这将是基于服务器的而不是嵌入式的。
我知道内存键值存储对我不起作用,因为我需要丰富的查询能力。
我知道 MySQL 可以做基于内存的表,但不确定人们是否将这个功能用于我的想法。SQL Server 可以在内存中固定表吗?整张桌子?
我应该查看哪些其他数据存储?如果快速,Map/Reduce 样式查询也可以。
我希望能够在数据存储中运行一组记录/文档,但始终让这些记录在 RAM 中保持新鲜。我只需要使用大约 1.5GB 到 2GB 的 RAM(可能更少)。这将是基于服务器的而不是嵌入式的。
我知道内存键值存储对我不起作用,因为我需要丰富的查询能力。
我知道 MySQL 可以做基于内存的表,但不确定人们是否将这个功能用于我的想法。SQL Server 可以在内存中固定表吗?整张桌子?
我应该查看哪些其他数据存储?如果快速,Map/Reduce 样式查询也可以。
VoltDB是一个内存中符合 ACID 的 SQL 数据库,针对高速 OLTP 进行了优化。它在 64 位 Linux 或 Mac OS X 上运行,具有开源社区版和多种语言的客户端库。
当您说“丰富的查询能力”时,听起来它可能更像是一个 OLAP 用例,但如果查询具有基本的复杂性,它可能非常适合 VoltDB。你能分享更多关于你的用例吗?
如果您可以将您的数据表示为对象的集合,那么您可以使用Linq作为您的“丰富查询”功能并在内存中完成所有操作:这将比几乎所有的数据库解决方案快得多。如果您可以将所有数据保存在内存中,那么甚至不必为数据库而烦恼。
注意:如果您在 .NET 中执行此操作,那么您必须在 64 位模式下构建您的项目,因为在 32 位应用程序上,您的 RAM 中的数据不能超过 ~1.5 GB。如果您不能在 64 位模式下构建/运行,那么您可能需要一个数据库。
我不确定我是否遵循你所说的:我不确定什么是流行系统,这会让我相信我没有使用流行系统。我也不知道什么是“本土”对象或什么是“本土”.NET 系统。我只使用标准的 .NET 4.0,当我说对象时,我特别指的是您编写可以保存数据的类。从那里开始,您将数据加载到内存中(我不知道您如何获取数据:文件、数据库、网络等),然后 Linq 为您执行 ORM。线程安全仅在您访问内部对象集合时才重要,您可以使用简单的锁来做到这一点。
哦,如果它是本地开发的 .NET 系统 - 这些对象是否托管在服务器上并被多个客户端访问?
对于我正在处理的数据,我不需要任何丰富的查询功能(既不需要在内存中,也不需要从数据库中获取),这就是为什么我们将无法放入内存的任何内容存储到嵌入式数据库中(水平数据库)。这样,我们所有的数据都包含在磁盘上,当我们需要它时,我们会采取最短/最快的路线将其放入内存。通过网络只会减慢您的速度,因此您可以这样做,但只有在绝对必要时才这样做(即您有一个硬约束,即您的 2GB 数据位于本地计算机以外的某个数据库上)。
SQLLite 可以在内存中运行用于关系数据库解决方案。对于非关系型数据库,RavenDB 可以在内存中运行。
我必须同意 Lirik 的观点。在 .Net 术语中,使用数据对象和 LINQ 查询它们的集合必须是完成您所要求的事情的最快方法之一,同时仍然拥有丰富的查询语言触手可及。
如果您担心集合的大小,并且如果您能够将所有信息保存在内存中,那么您可以查看Memcached等项目来帮助您。
更新
我已经构建了一个使用带有条件对象的 Linq 来查询产品列表的示例(尽管很容易成为 Linq to Sql 数据表)
首先是一个示例产品类:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Linq_Question
{
public class Product
{
public enum Categories
{
CatOne,
CatTwo,
CatThree
}
public int Id { get; set; }
public string Name { get; set; }
public Categories Category { get; set; }
public decimal Price { get; set; }
}
}
现在是一个示例产品标准类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Linq_Question
{
public class ProductCriteria
{
public Product.Categories? WhereCategoryIs { get; set; }
public decimal? WherePriceIsGreaterThan { get; set; }
public decimal? WherePriceIsLessThan { get; set; }
public string WhereNameContains { get; set; }
public ProductCriteria()
{
}
}
}
示例存储库 - 使用列表
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
namespace Linq_Question
{
public class ProductRepository
{
private List<Product> products;
public ProductRepository()
{
products = new List<Product>();
products.Add(new Product() { Category = Product.Categories.CatOne, Id = 1, Name = "Product 1", Price = 100 });
products.Add(new Product() { Category = Product.Categories.CatTwo, Id = 2, Name = "Product 2", Price = 120 });
products.Add(new Product() { Category = Product.Categories.CatThree, Id = 3, Name = "Product 3", Price = 300 });
products.Add(new Product() { Category = Product.Categories.CatOne, Id = 4, Name = "Product 4", Price = 400 });
products.Add(new Product() { Category = Product.Categories.CatTwo, Id = 5, Name = "Product 5", Price = 500 });
products.Add(new Product() { Category = Product.Categories.CatThree, Id = 6, Name = "Product 6", Price = 600 });
}
public IEnumerable<Product> Retrieve(ProductCriteria criteria)
{
return this.products.Where(FilterProducts(criteria));
}
private Func<Product, bool> FilterProducts(ProductCriteria criteria)
{
Expression<Func<Product, bool>> predicate = PredicateBuilder.True<Product>();
List<IProductFilter> filters = new List<IProductFilter>();
filters.Add(new PriceIsGreaterThanFilter());
filters.Add(new CategoryFilter());
foreach (var item in filters)
{
if (item.IsValidFilter(criteria))
{
predicate = predicate.And(item.ApplyFilter(criteria));
}
}
return predicate.Compile();
}
}
}
请注意,在 FilterProducts 方法中,过滤器列表在每个过滤器上循环,检查它是否是给定当前条件对象的有效过滤器,然后在需要时应用。
这是 IProductFilter 接口和一些示例过滤器
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
namespace Linq_Question
{
public interface IProductFilter
{
bool IsValidFilter(ProductCriteria criteria);
Expression<Func<Product, bool>> ApplyFilter(ProductCriteria criteria);
}
public class CategoryFilter : IProductFilter
{
public bool IsValidFilter(ProductCriteria criteria)
{
return (criteria.WhereCategoryIs.HasValue);
}
public Expression<Func<Product, bool>> ApplyFilter(ProductCriteria criteria)
{
return (p => p.Category == criteria.WhereCategoryIs.GetValueOrDefault());
}
}
public class PriceIsGreaterThanFilter : IProductFilter
{
public bool IsValidFilter(ProductCriteria criteria)
{
return (criteria.WherePriceIsGreaterThan.HasValue);
}
public Expression<Func<Product, bool>> ApplyFilter(ProductCriteria criteria)
{
return (p => p.Price > criteria.WherePriceIsGreaterThan.GetValueOrDefault());
}
}
}
请注意,您将需要 PredicateBuilder 类 - 发现http://www.albahari.com/nutshell/predicatebuilder.aspx
using System;
using System.Linq;
using System.Linq.Expressions;
using System.Collections.Generic;
namespace Linq_Question
{
public static class PredicateBuilder
{
public static Expression<Func<T, bool>> True<T>() { return f => true; }
public static Expression<Func<T, bool>> False<T>() { return f => false; }
public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expr1,
Expression<Func<T, bool>> expr2)
{
var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
return Expression.Lambda<Func<T, bool>>
(Expression.OrElse(expr1.Body, invokedExpr), expr1.Parameters);
}
public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expr1,
Expression<Func<T, bool>> expr2)
{
var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
return Expression.Lambda<Func<T, bool>>
(Expression.AndAlso(expr1.Body, invokedExpr), expr1.Parameters);
}
}
}
最后,这是一个小型控制台应用程序,展示了这个想法:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Linq_Question
{
class Program
{
static void Main(string[] args)
{
ProductRepository repo = new ProductRepository();
Console.WriteLine("Items over 100");
foreach (var item in repo.Retrieve(new ProductCriteria() { WherePriceIsGreaterThan = 100 }))
{
Console.WriteLine(string.Format("Name {0}, Category {1}, Price {2}", item.Name, item.Category, item.Price));
}
Console.WriteLine("Items with a Category of Two");
foreach (var item in repo.Retrieve(new ProductCriteria() { WhereCategoryIs = Product.Categories.CatTwo }))
{
Console.WriteLine(string.Format("Name {0}, Category {1}, Price {2}", item.Name, item.Category, item.Price));
}
Console.Read();
}
}
}
您可以扩展此想法以添加多个过滤器,甚至可以确定从 IProductFilter 返回的函数是否应该与表达式进行 AND 或 OR'd。
过滤器可以注入到存储库中 - 使它们在运行时易于更改。
我希望这能给你一些想法。