我遇到一个问题,DAL2存储库的默认Get()函数需要几秒钟才能返回结果。当我使用SQL Server Management Studio直接查询数据库以获取记录时,查询会快速返回。该函数是一个基本函数,如下所示:
public MyThing Get(string primaryKey)
{
MyThing myThing;
using (IDataContext ctx = DataContext.Instance(“DATABASECONN”))
{
var rep = ctx.GetRepository<MyThing>();
myThing = rep.GetById(primaryKey);
}
return myThing;
}
该表有800K +条目。
即使启用了缓存设置,该函数在后续执行中也具有相同的执行时间。
为什么这种功能很慢,我怎样才能加快速度呢?
答案 0 :(得分:4)
我在调试代码时在数据库上运行SQL事件探查器。它表明,第一次调用GetById()函数时,将执行从数据库表中选择所有记录的查询。主键未传递到数据库。下次执行GetById()函数时,不会查询数据库。结果从缓存的值返回。
因此,从GetById()函数返回的单个记录必须是对表中所有记录的结果集进行一些搜索的结果。有关此函数如何操作和检索记录的详细信息都在编译代码中(此编译代码的源代码可能可用,但我尚未对其进行调查)。
我查看了执行此代码期间的内存使用情况,以确保IIS有足够的数量。 IIS中的设置被设置为允许应用程序池使用可用内存。调试w3wp.exe进程的内存使用情况时,在.75和1.3 GB之间波动。有足够的额外RAM可用,因此如果需要,网站可以使用更多。
这些实验的亮点是:
为了解决这个问题,我改变了方法。在SELECT期间使用主键直接查询数据库时,查询会快速返回。这导致我使用DAL2存储库的Find()函数,所以我可以自己指定SELECT的条件 我创建的函数如下所示:
public MyThing Get(string primaryKey)
{
MyThing myThing = (MyThing)DataCache.GetCache(primaryKey);
if (myThing != null)
return myThing;
IList<MyThing> myThings;
using (IDataContext ctx = DataContext.Instance(“DATABASECONN”))
{
var rep = ctx.GetRepository<MyThing>();
myThings = (IList<MyThing>)rep.Find("WHERE myPrimaryKeyFieldName = @0", primaryKey);
if (myThings.Count > 0)
DataCache.SetCache(primaryKey, myThings[0]);
}
return myThings.Count > 0 ? myThings[0] : null;
}
上面的函数使用Find()函数,因此DAL2不实现缓存。为了解决这个问题,我提供了一种自定义缓存技术。使用SQL事件探查器调查此函数表明,使用相同的primaryKey值重复调用该函数没有命中数据库,因此缓存的行为符合预期。
以这种方式使用的缓存不会像使用GetById()时那样减慢执行时间。放置在函数中的DateTimes用作计时器,显示以下执行时间。当数据库被命中时,00:00:00.1或更低。当高速缓存命中时,执行时间为0.这没有大规模测试,但在我运行的测试中执行时间是一致的。
上述测试和解决方案显示DAL2中的GetById()应谨慎使用。根据数据库的大小,它不一定是检索记录的最佳解决方案。如果数据检索执行缓慢,请探索替代方法,例如解决方案中建议的方法。
在表格中确定GetById()不再是最佳解决方案的确切记录数将会很有帮助。此数字可能会根据对象中数据的大小而有所不同。它可能是可计算的,但目前没有等式,因此需要根据具体情况计算出来。
如果其他人有关于此主题的额外信息,请将其添加到讨论中。