在巨大的数据库表中有效地维护不同项的缓存

时间:2009-08-05 15:26:03

标签: asp.net sql-server sql-server-2005 caching

我有一个非常大(数百万行)的SQL表,它表示名称 - 值对(一列是属性名称,另一列是它的值)。在我的ASP.NET Web应用程序中,我必须使用name列中可用的不同值填充控件。这组值通常不大于100.最有可能在20左右。运行查询

  

SELECT DISTINCT name FROM nameValueTable

可能会占用这个大表(即使使用正确的索引等)。我每次加载这个网页控件时都特别不想支​​付这笔罚款。

因此缓存这组名称应该是正确的答案。我的问题是,如果表中有新名称,如何及时更新集。我调查了SQL 2005 Query Notification feature。但是表格经常更新,很少有实际的新的不同名称字段。通知将一直流动,并且通过设置此消息,Web服务器可能会浪费更多时间。

我想找到一种方法来平衡用于查询数据的时间,以及更新名称集之前的延迟。

有关如何有效管理此缓存的任何想法?

5 个答案:

答案 0 :(得分:2)

稍微规范化可能有所帮助。将属性名称分解为新表,并使用int ID将FK分解回原始表。你可以显示新表来获得完整的列表,这将非常快。

答案 1 :(得分:2)

确定您的使用模式将有助于您找到合适的平衡点 新增价值的频率是多少?添加的新值始终是唯一的吗?表大多是更新?删除会发生吗?

一种方法可能是让SQL Server插入触发器来检查表缓存以查看其密钥是否存在&如果它不是自我添加

答案 2 :(得分:1)

在表格中添加一个独特的增加序列MySeq。您可能希望尝试在MySeq上进行集群而不是当前的主键,以便DB可以构建一个小集,然后对其进行排序。

SELECT DISTINCT name FROM nameValueTable WhereSeq> =?; 设置?到您的缓存最后一次看到更新。

您的缓存和数据库之间总是存在延迟,因此,如果这是一个问题,您需要重新考虑应用程序的流程。如果管理数据,您可以尝试让所有请求流过缓存/应用程序:

请求 - >缓存 - >分贝

答案 3 :(得分:0)

如果您不允许更改此巨大表的实际结构(例如,由于依赖它的大量报告),您可以创建这20个值的保留表并对此进行查询。然后,在巨大的表上,有一个触发器在INSERT或UPDATE上触发,检查新的NAME值是否在保持表中,如果没有,则添加它。

答案 4 :(得分:-1)

我不知道.NET的细节,但我会通过缓存传递所有更新请求。是否所有更新请求都由ASP.NET Web应用程序完成?然后,您可以为数据库创建一个Proxy对象,并将所有请求定向到它。考虑到您的数据库只有键值对,很容易在Map中使用Proxy作为缓存。

具体来说,在伪代码中,所有请求都如下:

// the client invokes cache.get(key)
if(cacheMap.has(key))  { 
    return cacheMap.get(key);
} else { 
    cacheMap.put(key, dababase.retrieve(key));
}

// the client invokes cache.put(key, value)
cacheMap.put(key, value);
if(writeThrough) {
    database.put(key, value);
}

此外,在后台,您可以拥有一个Evictor线程,以确保缓存不会变大。在您的场景中,如果您经常访问一组值,我会根据空闲时间设置驱逐策略 - 如果某个项目闲置超过一定时间,则将其逐出。这可确保频繁访问的值保留在缓存中。此外,如果您的缓存不是直写,则需要让逐出器在驱逐时写入数据库。

希望有所帮助:)

-- Flaviu Cipcigan