我有一个包含大量行(300万)的表,我需要从我的应用程序中的多个点查询某些行。我发现这样做的方式是在第一次需要时查询所有数据,并将static DataTable
与SqlAdapter.Fill()
存储在应用程序生命周期的剩余时间内。
这很快,因为当我需要的时候我使用DataTable.Select("some query")
并且应用程序处理的信息很好。
问题是这个表需要大约800MB的RAM,而且我必须在可能太多的PC上运行这个应用程序。
我想的另一种方法是每次查询我需要的数据。这需要很少的内存,但性能很差(对数据库的大量查询,在网络地址和1000个查询,你开始注意到ping和所有......)。
性能和内存使用之间是否存在中间点?
编辑:我正在检索的是销售,它有日期,产品和数量。我按产品查询,并没有这样索引。但无论如何,进行1000次查询,即使查询占用0.05s,0.2s ping也总共需要200秒......
答案 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,所有查询都会进入网络(从而牺牲性能)。
下面将回答关于缓存设计的三个重要问题。
如何填充缓存?
有效的想法是如果您知道将来可能需要某些信息,请事先将其缓存。
如何释放缓存?
您可以决定缓存的释放机制主动或被动。
被动:每当缓存已满,您就可以从中删除数据。
积极主动:定期运行后台线程,并为您解决问题。
一种混合方法是在你到达时运行一个释放线程,比如80%的内存限制,然后释放任何内存。
要从缓存中删除哪些数据?
在操作系统Page Replacement Policies问题的背景下已经回答了这个问题。
为了完成,我将在这里总结一下重要的内容:
答案 2 :(得分:0)
RE:“我不能做任何索引,因为我不是数据库管理员,也不能要求。”
您可以预先填充临时表和索引吗?例如
Select * into #MyTempTable from BigHugeTable
Create Index Prodidx on #MyTempTable (product)
您必须确保始终重复使用相同的连接(并且未关闭)才能使用临时表。