1

I am having trouble with the performance of a query I am trying to write. I have a table with about 6000 records within it.

Currently its taking about 15 seconds to run on my development machine. A win8 machine with 32gb ram quadcore running vs2012 & sql2012. So its not my machine its my bad code.

    public IEnumerable<Customer> GetByStoreIdAndContainingName(Guid storeId, string containing)
    {
        using (var context = new Entities())
        {
            var store = context.Stores.FirstOrDefault(b => b.StoreId == storeId);
            if (store == null) return null;
            var business = store.Business;
            var consumers = new List<Consumer>();


            consumers =
                business.ConsumerIdentities.Select(ci => ci.Consumer)
                        .Distinct()
                        .Where(x => x.FirstName.ToLower().Contains(containing.ToLower()))
                        .ToList();

The layout of the database tables are

Business

BusinessId
Name
etc

StoreId

StoreId
StoreName
BusinessId

Consumer

ConsumerId
FirstName
LastName

ConsumerIdentities

BusinessId
ConsumerIdentityType
ConsumerIdentityValue

Can anyone see any obvious things I am doing wrong that would be taking so long to return the query results?

Turning on SQL Profiler was scary. The first query made was to select everything from ConsumerIdentity table where the business Id matched. Great that's perfect then gets the business table table.

However then seems to make a call for every single record like

exec sp_executesql N'SELECT 
[Extent1].[ConsumerId] AS [ConsumerId], 
[Extent1].[UserID] AS [UserID], 
[Extent1].[FirstName] AS [FirstName], 
[Extent1].[LastName] AS [LastName], 
[Extent1].[IsMale] AS [IsMale], 
[Extent1].[DateOfBirth] AS [DateOfBirth], 
FROM [dbo].[Consumer] AS [Extent1]
WHERE [Extent1].[ConsumerId] = @EntityKeyValue1',N'@EntityKeyValue1     uniqueidentifier',@EntityKeyValue1='952ED7B8-2123-49E2-BAE3-69FBD713BACB'

So it looks like my where statement isn't getting applied

4

4 回答 4

1

我将从 Customer 开始(如果属性存在),因为它Distinct首先保存 a 并且它应该在一个 SQL 语句中完成所有事情:

from c in Customer
where c.FirstName.ToLower().Contains(containing.ToLower())
      && c.ConsumerIdentity.Business.StoreId == storeId
select c

这并没有带走whereon c.FirstName.ToLower()。这样的结构总是会影响性能,因为它们不是sargable(它们消除了任何索引)。EF 目前没有工具来进行不区分大小写的搜索(它不接受Contains带有 的重载IEqualityComparer),因此从技术上讲,您无法避免这种情况。但是很可能数据库排序规则不区分大小写,因此x.FirstName.Contains(containing.ToLower()可能会给出相同的结果,索引

于 2013-02-04T08:51:12.050 回答
0

如果您在 Where 之后执行 Select 是否有帮助?

        consumers =
            business.ConsumerIdentities
                    .Where(x => x.FirstName.ToLower().Contains(containing.ToLower()))
                    .Distinct()
                    .Select(ci => ci.Consumer)
                    .ToList();
于 2013-02-03T00:40:49.317 回答
0

有几种优化方法可能会减少处理时间(其他人告诉过),但您查询的任何方式都是在具有 6000 条记录的数据库上执行搜索过程。但是对于 6000 条记录,它应该比 15 秒快。

这可能是因为您的内存缓存。我建议清除您的 VS 和系统缓存,然后重试。(您可以使用 C-Cleaner 应用程序进行系统缓存)

您也可以在 ADO 中使用异步启动。它对减少处理时间有很大的作用。(您可以使用支持异步的 IDataReadables 和 IDataReaders 来完成)

于 2014-01-16T12:14:00.290 回答
0

我只看到一件事可以改进:

  • 在( is a O(n log n) in O(n))Distinct之后使用WhereDistinctWhere

        consumers =
            business.ConsumerIdentities.Select(ci => ci.Consumer)
                    .Where(x => x.FirstName.ToLower().Contains(containing.ToLower()))
                    .Distinct()
                    .ToList();
    

但我怀疑您的性能问题来自 LINQ 查询(无论如何,6000 条记录应该非常快)。

于 2013-02-03T00:07:30.603 回答