【问题标题】:Why does the default GetById() for a DAL2 repository in DNN execute slowly?为什么 DNN 中 DAL2 存储库的默认 GetById() 执行缓慢?
【发布时间】:2013-11-29 11:08:18
【问题描述】:

我遇到了一个问题,即 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+ 个条目。

即使启用了缓存设置,该函数在后续执行中的执行时间也相同。

为什么运行缓慢?如何加快速度?

【问题讨论】:

    标签: sql dotnetnuke data-access-layer dotnetnuke-7


    【解决方案1】:

    调查

    我在调试代码时在数据库上运行了 SQL Profiler。它表明第一次调用 GetById() 函数时,执行了一个从数据库表中选择所有记录的查询。主键不传递给数据库。下次执行 GetById() 函数时,不再查询数据库。结果从缓存值返回。

    因此,从 GetById() 函数返回的单个记录必须是对表中所有记录的结果集进行某种搜索的结果。这个函数如何操作和检索记录的细节在编译代码中(这个编译代码的源可能是可用的,但我还没有调查过)。

    我查看了执行此代码期间的内存使用情况,以确保 IIS 有足够的数量。 IIS 中的设置被设置为允许应用程序池使用可用内存。在调试 w3wp.exe 进程的内存使用情况时,内存使用量在 0.75 和 1.3 GB 之间波动。有大量可用的额外 RAM,因此网站可以在需要时使用更多。

    这些实验的亮点是:

    • GetById() 函数第一次访问数据库表时,它将选择表中的所有记录。
    • 缓存按预期运行,因此重复查询不会命中数据库。
    • 无论 IIS 有多少可用内存,从缓存中检索结果都需要几秒钟的时间。

    解决方案

    为了解决这个问题,我改变了我的方法。在 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 Profiler 调查此函数表明,使用相同的 primaryKey 值重复调用该函数并没有命中数据库,因此缓存的行为符合预期。

    以这种方式使用的缓存不会像使用 GetById() 时那样减慢执行时间。 DateTimes 放置在函数中,用作计时器,显示以下执行时间。当数据库被命中时,00:00:00.1 或更小。当缓存被命中时,执行时间为 0。这没有进行大规模测试,但在我运行的测试中执行时间是一致的。

    结论

    上述测试和解决方案表明,应谨慎使用 DAL2 中的 GetById()。根据数据库的大小检索记录不一定是最佳解决方案。如果数据检索执行缓慢,请探索替代方法,例如解决方案中建议的方法。

    找出表中 GetById() 不再是最佳解决方案的确切记录数会很有帮助。此数字可能会因对象中数据的大小而异。它可能是可计算的,但目前没有等式,因此需要根据具体情况来计算。

    如果其他人对此主题有额外的信息,请将其添加到讨论中。

    【讨论】:

    • 我希望我是那么了不起!我试图通过搜索网络找到这个问题的答案,但我没有找到任何东西。在发布问题之前,我喜欢尝试自己解决问题,结果在这种情况下,我能够提出一个可接受的解决方案。我决定在这里分享我的努力成果,因为它似乎没有记录在我能找到的任何地方。我知道这看起来很奇怪,但正如这里指出的那样鼓励这样做,blog.stackoverflow.com/2011/07/…
    • +1 这正是本论坛鼓励的内容类型。您的问题和解决方案都有据可查。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-08-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-02
    • 1970-01-01
    • 2012-02-13
    相关资源
    最近更新 更多