具有共享条件的高效查询数据

时间:2018-11-16 00:37:14

标签: sql database performance entity-framework

我有多组数据,这些数据集是从实体框架代码优先的上下文(SQL CE)中获取的。有一个GUI显示每个查询集中的记录数,并在更改某些设置条件(例如日期)后,所有这些集都需要重新计算其“计数”值。

尽管每个集合的查询在某种程度上略有不同,但大多数查询在某种程度上共享共同的条件。一个简单的例子:

RelevantCustomers = People.Where(P=>P.Transactions.Where(T=>T.Date>SelectedDate).Count>0 && P.Type=="Customer")
RelevantSuppliers = People.Where(P=>P.Transactions.Where(T=>T.Date>SelectedDate).Count>0 && P.Type=="Supplier")

问题是,这些苛刻的查询已经足够了,每当用户更改某种条件(例如SelectedDate)时,重新计算每个集合中的记录数将花费很长时间。

我意识到,这样做的部分原因是需要例如每次查询交易,以检查RelevantCustomers和RelevantSuppliers的相同条件到底是什么。

所以我的问题是,考虑到这些集合共享共同的“基本条件”(取决于相同的数据集),我是否可以通过一些更有效的方式来计算这些集合?

我正在考虑使用这样的自定义通用类:

QueryGroup<People>(P=>P.Transactions.Where(T=>T.Date>SelectedDate).Count>0)
{
     new Query<People>("Customers", P=>P.Type=="Customer"),
     new Query<People>("Suppliers", P=>P.Type=="Supplier")
}

我可以很好地构建这种结构,但是我发现它基本上没有影响效率,因为它仍然需要为每个集合重复“共享条件”。

我还尝试过先将基本条件数据作为静态“ ToList()”拉出,但这会在遇到导航实体时出现问题(即,不加载People.Address)。

在效率方面我是否不了解某些方法?

谢谢!

1 个答案:

答案 0 :(得分:1)

尝试这样的操作:将“相似”的值组合到较少的查询中,然后再分离结果。另外,使用Any()而不是Count()进行是否存在检查。您的更新尝试是中途进行的,但仍然会导致数据库命中率达到2倍。同样,在查询时,它有助于确保您正在针对索引字段进行查询,并且使用数字ID而不是字符串,这些索引将更加有效。 (即,“客户”与“供应商”的TypeID为1相对于2)。标准化的值更适合于索引编制,并导致记录变小,但要付出额外的冗长查询费用。

var types = new string[] {"Customer", "Supplier"};
var people = People.Where(p => types.Contains(p.Type)
  && p.Transactions.Any(t => t.Date > selectedDate)).ToList();
var relevantCustomers = people.Where(p => p.Type == "Customer").ToList();
var relevantSuppliers = people.Where(p => p.Type == "Supplier").ToList();

这只会导致数据库命中一次,并且Any的性能应比获取整个计数高。我们从内存集合中分离出客户和供应商。需要注意的是,任何尝试访问客户和供应商上的交易等详细信息的尝试都会导致延迟加载命中,因为我们不希望加载它们。如果需要整个实体图,请确保包含.include()相关详细信息,或者对从第一个查询提取的数据更具选择性。即选择具有适用详细信息的匿名类型,而不仅仅是实体。