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

Posted

技术标签:

【中文标题】在巨大的数据库表中有效地维护不同项目的缓存【英文标题】:Efficeintly maintaining a cache of distinct items in a huge DB table 【发布时间】:2009-08-05 15:26:02 【问题描述】:

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

从名称值表中选择不同的名称

在这个大表上可能会花费大量时间(即使使用正确的索引等)。我特别不想每次加载这个 web 控件时都支付这个惩罚。

所以缓存这组名称应该是正确的答案。我的问题是,当表中有新名称时如何及时更新集合。我调查了SQL 2005 Query Notification feature。但是该表会经常更新,很少使用实际的新的不同名称字段。通知将一直流入,并且网络服务器可能会浪费更多的时间而不是通过设置节省的时间。

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

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

【问题讨论】:

是否可以从表中删除不同的名称?如果是这样,我假设您希望您的缓存也反映这一点? 现在你知道为什么这是糟糕的数据库设计模式了。 我是否正确理解您有一个包含两列(名称、值)的表,并且给定的名称可以有多个值?在所有可用值中,您如何决定使用哪一个? 【参考方案1】:

稍微标准化可能会有所帮助。使用 int ID 将属性名称拆分到新表中,然后 FK 回到原始表中。您可以显示新表以获取完整列表,这将非常快。

【讨论】:

【参考方案2】:

弄清楚您的使用模式将帮助您找到正确的平衡点。 多久添加一次新值?添加的新值总是独一无二的吗?表主要是更新吗?会发生删除吗?

一种方法可能是使用 SQL Server 插入触发器,该触发器将检查表缓存以查看其键是否存在以及是否不添加自身

【讨论】:

【参考方案3】:

将唯一的递增序列 MySeq 添加到您的表中。您可能想尝试在 MySeq 上而不是您当前的主键上进行集群,以便数据库可以构建一个小集合然后对其进行排序。

SELECT DISTINCT name FROM nameValueTable Where MySeq >= ?; 放 ?到您的缓存上次看到更新的时间。

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

请求 --> 缓存 --> 数据库

【讨论】:

@KM 我喜欢你的解决方案更好。问题是表中有多少不同的值? @Justin,OP 说“这组值通常不大于 100。很可能在 20 左右。”【参考方案4】:

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

【讨论】:

【参考方案5】:

我不知道 .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

【讨论】:

以上是关于在巨大的数据库表中有效地维护不同项目的缓存的主要内容,如果未能解决你的问题,请参考以下文章

如何有效地将巨大的 sql 表加载到 asp.net 应用程序内存中以进一步迭代它?

如何有效地维护传递闭包表?

memcached缓存技术

安装Memcache缓存

更新两个不同表中的字段的最有效方法?

Java中使用memcache缓存