字符串太长时无法执行查询

时间:2019-04-11 12:02:54

标签: c# sql-server

我正在尝试运行通常可以正常运行的查询,但是如果列表太大,则会出现超时错误。

这是我的代码:

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查询中处理海量数据的好解决方案或好方法是什么?

谢谢。

2 个答案:

答案 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)并多次查询数据库。