我正在尝试运行通常可以正常运行的查询,但是如果列表太大,则会出现超时错误。
这是我的代码:
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),则可以正常工作。但是,如果计数大约为100万,则会导致SQL超时异常。
当我查看SQL事件探查器时,我发现查询甚至没有运行。
我在做什么错?在C#=> SQL Server查询中处理海量数据的好解决方案或好方法是什么?
谢谢。
答案 0 :(得分:3)
我在这里看到多个问题,然后尝试在这里退后一步:
首先,正如其他人提到的那样,传递参数的方式不是最理想的。 <div class="bg"></div>
不能传递这么长的参数列表。在这种情况下,IN会使用大量资源,很可能导致您发现问题。
为此的技术解决方案是创建一个临时表或使用并连接用户表。正如评论中指出的那样,这不是同一件事,并且FROM(VALUES())在某些情况下可以工作,但在其他情况下则不能。
使用临时表,看起来像
IN
也可以使用 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(...))
我注意到的第二件事是该查询始终加载完整的用户对象。我假设调用方法会对那些仅是用户数据子集的用户进行某些操作?在这种情况下,只返回应用程序特定步骤中所需的数据并进行有限的选择会更干净。这样可以减少需要从磁盘读取并大量传输到应用程序的数据量,因此可以极大地提高性能
答案 1 :(得分:1)
一种方法可能是将ids
的名称拆分为几位,比如说100K(因为它使用的是相同数量的ID)并多次查询数据库。