【问题标题】:Very Slow Linq to SQL Select Performance on WP7WP7 上的 Linq to SQL 选择性能非常慢
【发布时间】:2011-11-01 17:47:50
【问题描述】:

我在 Windows Phone 7 上遇到了 Linq to SQL 性能问题,但我真的不确定我做错了什么(我几乎没有使用 Linq to SQL 的经验,而且我阅读的越多,我越来越困惑了叹气)。

背景

我有一个本地 SQL CE 数据库,其中包含五个表,每个表中有两列(int 主键和nvarchar 值,加上索引),每个表中大约有 100,000 个条目。数据库大小约为 20MB,按照 Microsoft 自己的 MVVM 本地数据库示例中的指南实施。

问题

尽可能简化后,我的视图模型中有一个查询,如下所示:

var query =
(
  from t1 in db.table1
    join t2 in db.table2 on t1.id equals t2.id
    join t3 in db.table3 on t1.id equals t3.id
    join t4 in db.table4 on t1.id equals t4.id
    join t5 in db.table5 on t1.id equals t5.id
  where
    SqlMethods.Like(t5.value, "%"+searchTerm+"%")
  select new Results
  {
    Field1 = t1.value,
    Field2 = t2.value,
    Field3 = t3.value,
    Field4 = t4.value,
    Field5 = t5.value,
  }
).Take(100);

SearchResults = new ObservableCollection<Results>(query);

此产品产生以下 SQL:

SELECT TOP (100)
  [t0].[value] AS [Field1],
  [t1].[value] AS [Field2],
  [t2].[value] AS [Field3],
  [t3].[value] AS [Field4],
  [t4].[value] AS [Field5]
FROM
  [table1] AS [t0],
  [table2] AS [t1],
  [table3] AS [t2],
  [table4] AS [t3],
  [table5] AS [t4]
WHERE ([t4].[value] LIKE @p0)
  AND ([t0].[id] = [t4].[id])
  AND ([t0].[id] = [t3].[id])
  AND ([t0].[id] = [t2].[id])
  AND ([t0].[id] = [t1].[id])

问题是,当搜索词非常具体(只有一个结果)时,平均执行时间约为 5 秒。这是在我添加任何其他要求之前,例如多个 where 子句、排名、排序等。即使我搜索我知道的数据库中的第一行,它仍然需要大约 5 秒。

如果我改变方法并搜索一些非常常见的内容(例如“the”),则只需大约 100 毫秒 即可执行。我知道带有通配符的Like 比直接比较== 更复杂,但我不知道为什么性能如此不同。

(我知道这是无用的比较,因为它们是苹果和橘子,但我之前在用 MySQL 编写的同一个数据库上执行了类似的查询,无论我搜索什么,它们始终在大约 0.3-0.4 秒内得到结果)。

我是否遗漏了一些非常明显的东西?我已经按照 Microsoft 的示例并在线阅读了许多教程,但我找不到这个查询如此缓慢的原因。非常感谢您提供的任何建议。

【问题讨论】:

  • 我强烈建议您尝试不使用使用 LINQ 执行相同的查询。我怀疑您会看到相同的性能,这意味着根本不应该归咎于 LINQ。请记住,通过这样的通配符搜索,数据库基本上不能使用任何索引 - 而通过直接相等匹配,它应该能够非常快速地找到正确的条目。
  • 感谢乔恩的快速回复。你是对的,我刚刚使用生成的 SQL 在我的桌面上分析了同一个数据库,并获得了相似的性能比(特定查询为 1.2 秒,通用查询为 0.02 秒)。我没有意识到通配符会对性能产生如此大的影响。

标签: c# sql linq-to-sql windows-phone-7


【解决方案1】:

简单的常识。

  • 您在低功耗手机上运行它并进行表扫描查询。

SqlMethods.Like(t5.value, "%"+searchTerm+"%")

表示没有索引抓取,这是一个表扫描。

).Take(100);

意思是:找到100个项目后停止。

现在,用一个非常常见的词(“the”)来说,这可能意味着只处理了 100 个项目。用一个更不常见的词,它可能需要跑一半的桌子才能得到 100 个项目。表扫描该数据库的一半需要时间。辛普。

一般来说,sql 对文本中的单词解析准备不足——这就是真正的 sql server ahs 全文索引的原因。在低功耗硬件上运行 (%word%)(wp7= 自然很慢。

这里绝对没有任何内容表明 LINQ 存在问题。 LINQ 可能会在您在查询中定义的性能边界内将其转换为非常有效的 SQL 查询 - 遗憾的是,这是您对数据库所做的最糟糕的事情。

【讨论】:

  • 谢谢汤姆,看了这么久,我觉得我的常识越来越低了!你的解释很清楚,我想我只是认为(希望?)我对 Linq 缺乏了解是罪魁祸首。我想我需要重新格式化我的查询和/或数据以避免这种通配符的情况,但我很挣扎。无论如何,感谢您的时间并指出应该显而易见的内容:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多