【问题标题】:Dapper sql too slow when in parameter is list string当参数是列表字符串时,Dapper sql 太慢了
【发布时间】:2021-05-27 00:23:08
【问题描述】:

我在 Dapper 中使用带有参数的原始 SQL。查询速度正常。

类似这样的:

string sql = "SELECT * FROM SomeTable WHERE messages IN ('Volvo', 'BMW', 'Ford', 'Mazda')"
var results = conn.Query(sql);

当我用@messages更改参数时,速度太慢了:

string sql = "SELECT * FROM SomeTable WHERE messages IN (@cars)"
string[] cars = { "Volvo", "BMW", "Ford", "Mazda" };
var results = conn.Query(sql, new {cars});

PS:string[] 大小几乎是 300。

【问题讨论】:

  • 查询由服务器执行,而不是 Dapper。它的性能取决于messages 是否被索引。
  • 也许您可以跟踪执行的查询并检查计划以确定有什么不同?
  • string[] size is almost 300. 您是否尝试过使用包含 300 个项目的原始字符串?不可能将值数组作为参数传递,因此 Dapper 实际上会生成一个带有这些值的 IN 子句。这两个查询应该是相同的。
  • @PanagiotisKanavos 实际上,我相信 Dapper 将创建一个包含 300 个 sql 参数的查询,而不是另一个在查询中硬编码值的查询。所以使用参数可能会产生一些开销,但我怀疑它会不会很明显。
  • @juharr 在这种情况下,服务器将无法计算这些值的统计信息。如果sometable 太小,服务器可能会决定使用扫描而不是查找,特别是因为它需要检索所有列。顺便说一句,没有表架构和行数,我们就像服务器一样盲目。

标签: c# dapper


【解决方案1】:

如果您将字符串作为参数传递,Dapper 会将其视为nvarchar 类型。 所以如果你的messagesvarchar 类型并且SomeTable 很大,即使它被索引,速度也可能非常慢。 DbString 可以解决这个问题。

cars.ToList().Select(x => new DbString { Value = x, IsFixedLength = false, IsAnsi = true });

【讨论】:

  • 对于列表类型的值,Dapper 会重写查询
【解决方案2】:

(作为评论会很混乱) (我认为第二个可能有一些语法错误,不应该有括号。)

这两个查询会生成不同的 SQL 发送到后端。即:使用 MS SQL 服务器,它们看起来像:

第一个:

SELECT * FROM SomeTable WHERE messages IN ('Volvo', 'BMW', 'Ford', 'Mazda')

第二个:

exec sp_executesql N'SELECT * FROM SomeTable WHERE messages IN (@cars1, @cars2, @cars3, @cars4)',
N'@cars1 nvarchar(4000),@cars2 nvarchar(4000),@cars3 nvarchar(4000),@cars4 nvarchar(4000)',
@cars1=N'Volvo',@cars2=N'BMW',@cars3=N'Ford',@cars4=N'Mazda'

恕我直言,根据您的后端,有更好的方式进行 IN 查询。

【讨论】:

  • 真正的区别在于,在第一个查询中,查询优化器可以根据值计算统计信息,因为它们是查询本身的一部分。在第二种情况下,这些值是未知的,只有它们的数量是已知的。这比甚至计数未知的 TVP 好一点
  • @PanagiotisKanavos,是的,这是不同的。我不会在这样的查询中进行参数化(它可以翻译为 EXISTS、INNER JOIN ...)。实际上,在 MS SQL 服务器的一个真实场景中,我结束了创建 CLR 函数。凭借超过 20K 的参数,它在一秒钟内针对 apprx 返回了结果。 50 万行。
猜你喜欢
  • 2017-10-23
  • 1970-01-01
  • 2012-12-01
  • 2021-09-24
  • 2015-02-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多