【问题标题】:Efficient caching strategy for DB entities with lookup by two fields通过两个字段查找的数据库实体的高效缓存策略
【发布时间】:2018-07-08 02:08:33
【问题描述】:

我已经实现了一个非常简单的查找缓存,以优化某些数据库实体的处理。缓存类如下所示:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SyncEngine.Caches
{
    class TenantsCache : Cache
    {
       System.Collections.Generic.List<tenant> list;

        public override void ReadFromDB()
        {
            using (var ctx = new MyContext())
            {
                this.list = ctx.tenants.ToList<tenant>();
            }
        }

        public override void Add(object o)
        {
            list.Add((tenant)o);
        }

        public tenant LookupByFNandGID(string fn, int groupId)
        {
            tenant match = null;
            foreach (tenant t in list)
            {
                if (t.friendlyName == fn && t.groupId == groupId) // <-- slowest line
                {
                    match = t;
                    break;
                }
            }
            return match;
        }
    }
}

通过分析 CPU 使用率,我发现这个 Lookup(特别是高亮行)占用了最多的处理时间。

是否有更好、更有效的方法来实现此查找/缓存和/或此处的比较?有没有更高效的内置集合,通过两个字段进行优化查找?

【问题讨论】:

  • 如果你想在数据库级别解决这个问题(你应该),分布式数据库就是你正在寻找的机器人。在性能重要的情况下或与主数据库的连接不可靠的情况下(移动应用程序),许多进程内数据库可以充当本地缓存数据库。对于 SQL,它将是 SQL Express。但是,当您对速度提出质疑时,我觉得有必要将速度咆哮联系起来:ericlippert.com/2012/12/17/performance-rant Particulary Parts 2 and 4 mater for your case.
  • 谢谢,但是是的,我真的需要回答这个问题,我不知道差异是否相关,直到我有一些东西可以比较。

标签: c# performance entity-framework caching


【解决方案1】:

您可以使用包含两个字段的自定义键创建字典:

class Key : IEquatable<Key>
{
    public string fn;
    public int groupId;

    public override bool Equals(object obj)
    {
        Key k = obj as Key;
        if (k == null)
        {
            return false;
        }
        else
        {
            return this.Equals(k);
        }
    }

    public bool Equals(Key other)
    {
        return this.fn == other.fn && this.groupId == other.groupId;
    }

    public override int GetHashCode()
    {
        return fn.GetHashCode() * 13 + groupId.GetHashCode();
    }
}

然后你可以使用比列表更快的字典:

Dictionary<Key, tenant> foo = new Dictionary<Key, tenant>();

【讨论】:

  • 鉴于Equals 的实现与我已经在做的比较相同,字典查找真的会更有效率吗?
  • 字典请求会在O(1)之后执行,同时foreach - O(N)。
  • 字典首先使用 GetHashCode 在它保存的内部哈希表中找到一个桶。一旦它缩小到一个存储桶,它就会使用存储桶中的 Equals 来查找您要查找的条目。这意味着即使对于包含数百万个项目的字典,它也只会调用 Equals 几次。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-06
  • 2011-11-23
  • 2010-10-29
  • 1970-01-01
  • 2015-07-21
相关资源
最近更新 更多