具有复合唯一ID的缓存对象的最佳数据结构

时间:2013-08-19 19:04:25

标签: c# caching data-structures

我有一个很慢的功能,它使得服务器的昂贵旅行来检索RecordHdr对象。这些对象先按照排除,然后按辅助排序。然后他们分批返回。

    | rid | aid |
    -------------->
    | 1   | 1   | >
    | 1   | 3   | >  
    | 1   | 5   | > BATCH of 5 returned
    | 1   | 6   | >  
    | 2   | 2   | >
    -------------->
    | 2   | 3   |
    | 2   | 4   |
    | 3   | 1   |
    | 3   | 2   |
    | 3   | 5   |
    | 3   | 6   |
    | 4   | 1   |
    | 4   | 2   |
    | 4   | 5   |
    | 4   | 6   |

在检索对象之后,我必须将它们包装在另一个名为WrappedRecordHdr的类中。 我想知道什么是最好的数据结构我可以用来维护WrappedRecordHdr对象的缓存,这样如果我通过rid和aid请求一个对象,我会返回一个特定的对象。此外,如果我被要求摆脱,我应该返回所有有摆脱的对象。

到目前为止,我已经为每个场景创建了两个结构(这可能不是最好的方式,但它是我现在使用的):

    // key: (rid, aid)
    private CacheMap<int, int, WrappedRecordHdr> m_ridAidCache =
        new CacheMap<int, int, WrappedRecordHdr>();

    // key: (rid)
    private CacheMap<int, WrappedRecordHdr[]> m_ridCache =
        new CacheMap<int, WrappedRecordHdr[]>();

另外,我想知道是否有一种方法可以重写它以提高效率。现在我必须得到一些我需要在另一个对象中包装的记录。然后,我需要通过id将它们分组到字典中,这样如果我被要求某个摆脱,我可以返回所有具有相同摆脱的对象。记录已经排序,所以我希望GroupBy不会事先对它们进行排序。

    RecordHdr[] records = server.GetRecordHdrs(sessId, BATCH_SIZE) // expensive call to server.

    // After all RecordHdr objects are retrieved, we loop through the received objects. For each RecordHdr object a WrappedRecordHdr object has to be created.
    WrappedRecordHdr[] wrappedRecords = new WrappedRecordHdr[records.Length];

    for (int i = 0; i < wrappedRecords.Length; i++)
    {
        if (records[i] == null || records[i].aid == 0 || records[i].rid == 0) continue; // skip invalid results.

        wrappedRecords[i] = new WrappedRecordHdr(AccessorManager, records[i], projectId);
    }

    // Group all records found in a dictionary of rid => array of WrappedRecordHdrs, so all records with the same 
    // rid are returned.
    objects associated to a particular rid.
    Dictionary<int, WrappedRecordHdr[]> dict = wrappedRecords.GroupBy(obj => obj.rid).ToDictionary(gdc => gdc.Key, gdc => gdc.ToArray());

    m_ridCache = dict;

1 个答案:

答案 0 :(得分:2)

关于数据结构,我认为这里确实存在两个不同的问题:

  1. 使用什么结构;
  2. 是否应该有一个或两个缓存;
  3. 在我看来,您需要一个缓存,键入为MemoryCache。密钥将是RID,值将是Dictionary,其中密钥是AID,值是标头。

    这具有以下优点:

    1. WrappedRecordHdrs仅存储一次;
    2. MemoryCache已经实现了所有缓存逻辑,因此您无需重写;
    3. 当只提供RID时,您知道每个WrappedRecordHdr的AID(在初始帖子中您没有使用该数组);
    4. 这些事总是妥协,所以当然也有缺点:

      1. 缓存访问(获取或设置)需要每次构造一个字符串;
      2. RID + AID查找需要索引两次(而不是编写一些快速散列函数,它接受RID和AID并将单个密钥返回到缓存中,但这需要您有两个缓存(仅一个RID,一个RID + AID)或每个AID存储两次相同的WrappedRecordHdr(一次用于RID + AID,一次用于null + AID);