如何从SQL Server缓存大表

时间:2015-08-27 12:57:56

标签: c# sql-server

我有一个包含大量行(300万)的表,我需要从我的应用程序中的多个点查询某些行。我发现这样做的方式是在第一次需要时查询所有数据,并将static DataTableSqlAdapter.Fill()存储在应用程序生命周期的剩余时间内。

这很快,因为当我需要的时候我使用DataTable.Select("some query")并且应用程序处理的信息很好。

问题是这个表需要大约800MB的RAM,而且我必须在可能太多的PC上运行这个应用程序。

我想的另一种方法是每次查询我需要的数据。这需要很少的内存,但性能很差(对数据库的大量查询,在网络地址和1000个查询,你开始注意到ping和所有......)。

性能和内存使用之间是否存在中间点?

编辑:我正在检索的是销售,它有日期,产品和数量。我按产品查询,并没有这样索引。但无论如何,进行1000次查询,即使查询占用0.05s,0.2s ping也总共需要200秒......

3 个答案:

答案 0 :(得分:3)

首先谈谈dba关于性能的问题

如果要下载整个表,实际上可能会比执行单个查询时对网络和SQL施加更多负载。

如果我知道你正在下载整个大表,那么我会立即在产品上加上索引。

为什么要执行1000次查询?

如果您在创建产品时正在寻找销售,那么缓存就会出现问题。您还没有销售数据。缓存的问题是陈旧的数据。如果你知道数据不会改变 - 无论你是否拥有它,你就可以消除对陈旧数据的担忧。

顺序和同时之间存在某种东西。您可以在单个请求中打包多个选择。这样做是一次往返,效率更高。

select * from tableA where ....;  
select * from tableB where ....; 

使用DataReader只需调用SqlDataReader.NextResult Method ()

using (SqlDataReader rdr = cmd.ExecuteReader())
{
   while (rdr.Read())
   {
   }
   rdr.NextResultSet();
   while (rdr.Read())
   {
   }
}

非常确定您可以在DataSet中使用多个DataTable执行相同类型的操作。

另一个选项是LocalDB。它针对的是开发人员,但对于你正在做的事情,它可以正常工作。 DataTable速度没有内存问题。您甚至可以在ProductID上添加索引。与内存相比,写入光盘需要更长的时间,但是你没有耗尽内存。

然后有一个邪恶的(nolock)。知道你在做什么,我不打算进入所有可能的邪恶,但我可以告诉你我经常使用它。

答案 1 :(得分:1)

问题可以归结为内存与性能。答案是缓存

如果你知道你的使用模式是什么样的,那么你可以做的一件事是在应用程序中创建一个本地缓存。

极端情况是 - 您的缓存大小为800MB,其中包含所有数据(从而牺牲内存) - 或者 - 您的缓存大小为0MB,所有查询都会进入网络(从而牺牲性能)。

下面将回答关于缓存设计的三个重要问题。

如何填充缓存?

  1. 如果您可能多次进行一些查询,请将其存储在缓存中,然后再进入网络,测试缓存是否已有结果。如果没有,请查询数据库,然后将结果存储在缓存中。
  2. 如果在查询了一些数据后,您可能会查询下一个和/或上一个数据,然后查询所有数据并对其进行缓存,以便在查询下一个数据时,您已将其存储在缓存中。
  3. 有效的想法是如果您知道将来可能需要某些信息,请事先将其缓存。

    如何释放缓存?

    您可以决定缓存的释放机制主动被动

    被动:每当缓存已满,您就可以从中删除数据。

    积极主动:定期运行后台线程,并为您解决问题。

    一种混合方法是在你到达时运行一个释放线程,比如80%的内存限制,然后释放任何内存。

    要从缓存中删除哪些数据?

    在操作系统Page Replacement Policies问题的背景下已经回答了这个问题。

    为了完成,我将在这里总结一下重要的内容:

    1. 逐出最近使用过的数据(如果不太可能使用);
    2. 排除最早提交的数据(如果最早的数据不太可能被使用);
    3. 删除最新带来的数据(如果您认为新引入的数据最不可能使用)。
    4. 自动删除早于 t 时间单位的数据。

答案 2 :(得分:0)

RE:“我不能做任何索引,因为我不是数据库管理员,也不能要求。”

您可以预先填充临时表和索引吗?例如

Select * into #MyTempTable from BigHugeTable 
Create Index Prodidx on #MyTempTable (product)

您必须确保始终重复使用相同的连接(并且未关闭)才能使用临时表。