[英]Cannot execute query when the string is too long
我正在尝试运行通常可以正常运行的查询,但是如果列表太大,则会收到超时错误。
这是我的代码:
public async Task<IEnumerable<User>> GetUsers(IEnumerable<int> ids)
{
if (ids.IsNullOrEmpty())
{
return Enumerable.Empty<User>();
}
string query = $@" SELECT *
FROM dbo.Users
WHERE Id IN ({string.Join(",", ids)})";
using (SqlConnection conn = new SqlConnection(ConnectionString))
{
return await conn.QueryAsync<TEntity>(query);
}
}
如果id数量很少(少于100K),则可以正常工作。 但是,如果计数约为1百万,则会导致SQL超时异常。
当我查看SQL事件探查器时,我发现查询甚至没有运行。
我究竟做错了什么? 在C#=> SQL Server查询中处理海量数据的一种好解决方案或好方法是什么?
提前致谢。
我在这里看到多个问题,然后尝试在这里退后一步:
首先,就像其他人提到的那样,传递参数的方式不是最理想的。 IN
不能传递这么长的参数列表。 在这种情况下,IN使用大量资源,很可能导致您发现问题。
为此的技术解决方案是创建一个临时表或使用并加入用户表。 正如评论中指出的那样,这不是同一件事,并且FROM(VALUES())在某些情况下可以工作,但在其他情况下则不能。
有了临时表,它看起来像
string query = $@" CREATE TABLE @ids (id INT);
INSERT INTO @ids VALUES {string.Join(",", ids.Select(id => $"({id})"))}
SELECT u.*
FROM @ids Ids
JOIN dbo.Users u ON u.Id = Ids.Id
也有可能使用FROM (VALUES(...))
,但是正如下面我的评论者所提到的,这不保证有效。 它看起来像这样:
string query = $@" SELECT u.*
FROM (
VALUES {string.Join(",", ids.Select(id => $"({id})"))}
) AS Ids(Id)
JOIN dbo.Users u ON u.Id = Ids.Id";
我注意到的第二件事是,此查询始终加载完整的用户对象。 我假设调用方法会对那些仅是用户数据子集的用户进行某些操作? 在这种情况下,只返回应用程序特定步骤中所需的数据并进行有限的选择会更干净。 这减少了需要从磁盘读取并大量传输到应用程序的数据量,因此可以极大地提高性能。
一种方法是将您的ids
集合划分为若干位,比如说100K(因为它可以处理该数量的ID)并多次查询数据库。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.