如何使用组合键索引集合

时间:2010-08-27 15:59:44

标签: c# performance collections concurrency composite-index

我有这个班级

public class Item
{
    public int UniqueKey;
    public int Key1;
    public int Key2;
    public int Key3;
    public int Key4;
    public string Value;
}

和集合IEnumerable<Item>

我想通过 Key1 Key2 或复合一个( Key1和Key4 )为此集合的项目创建索引。收集的物品数量约为10 000或更多。主要目标是表现。多个呼叫者可以具有许多读/写访问权限。应保护退回的集合(防止外部修改)。有人可以解释任何解决方案,模式,我必须用来实现的集合类。

由于某些原因(性能等),我拒绝使用数据库表索引的变体。

3 个答案:

答案 0 :(得分:1)

您可以使用两个映射:一个用于存储,另一个用作主键的查找表。由于所有更新都使用应修复的主键,因此可以使用锁定剥离来允许并发写入。在这种形式下,编写者必须获取一个锁(primaryKey mod#locks),以便更新/删除不会竞争条目。当然,如果后备字典是并发的,则读取不需要锁定。

你可以看到这个想法的Java version隐藏在缓存外观背后,以提供一个很好的API。

答案 1 :(得分:0)

您可以使用LINQ返回由属性索引的集合:

var key1 = from i in Items 
           group i by i.Key1 into g
           select g;

var key2 = from i in Items
           group i by i.Key2 into g
           select g;
...

由于您有一个小的,确定性的键列表,您可以实现一个类,该类公开组以供读取IEnumerableList属性。添加一个方法可以将项添加到集合中(不需要单独的方法,因为它们将根据其值进行分组以进行读取。)使用Add方法中的lock关键字在添加时保护项集合。

答案 2 :(得分:0)

您可以使用匿名类型对项目进行分组,并使用组创建字典:

var grouped = items.GroupBy(item => new { item.Key1, item.Key4 })
                   .ToDictionary(g => g.Key, g => g.ToList());

但是,匿名类型只能用于局部变量(或通用方法参数),因此如果您要存储字典以供以后重用,则需要非匿名类型。因此,您可以为每个可能的组合键创建类型,也可以使用Tuple类:

Dictionary<Tuple<int, int>, Item> grouped =
              items.GroupBy(item => Tuple.Create(item.Key1, item.Key2))
                   .ToDictionary(g => g.Key, g => g.ToList());