C#过滤器和C#应用程序中的语句

时间:2014-06-26 14:32:44

标签: c# sql .net collections ado.net

我有一个C#应用程序,我遇到了这个问题:当我运行这个代码片段时:

第一种方式

public void GetList(List<string> liste, List<int> outliste)
{
    foreach( string s in liste){
        outliste.Add(SqlFunction(s));
    }
}
public int SqlFunction(string str)
{
    string query = "select id from user where name="+str;
    ...................
    // return the id
}

执行时间为51秒

第二种方式

public void SqlSecondWayFunction(List<string> liste, List<int> outliste)
{

   string query ="select id from user where (";
   foreach(string str in liste){
       query += "name=" str + "or  ";
   }
   query += " 1=0 )";

   ...................
   // fill outliste by the result of the query
}

执行时间是1米:19秒!!!!!!!!! (liste的计数约为11000)。

所以我需要知道为什么第一种方式更快?

3 个答案:

答案 0 :(得分:2)

第一个更快,因为它做的事情更少。而且它只选择一个记录子集。

第二种是较慢的,因为你要连接大量的字符串(这样做很慢),并且为每个记录在数据库上执行数千次不必要的比较,只返回无论如何每个记录。

基本上,您要求数据库将name列与表中每条记录的11,000个字符串进行比较。例如,如果该表包含100,000条记录,那么您将进行 1,100,000,000 字符串比较。然后你还是会返回所有记录,因为你的一个条件是&#34; 1 = 1&#34; 总是是真的。

答案 1 :(得分:1)

一些事情:

  • 在WHERE子句中添加很长的OR列表通常效率不高,因为首先解析一个非常长的查询字符串需要花费一些时间,而且数据库引擎完成的内部工作也很长OR列表
  • 您添加的最后一部分(&#34; OR 1 = 1&#34;)使WHERE子句始终为TEST TRUE!它与没有WHERE子句
  • 相同
  • 上述任何一种情况都可能导致您的第一个简单查询示例比一个低效的大型查询花费的时间少
  • 您应该针对您的用例考虑以下其中一项:1)通过加载DataTable并使用&#34;从用户&#34;中选择id来获取id列表,调用DataTable.AsEnumerable()方法,然后使用LINQ查询连接到您的其他列表,2)首先将列表加载到数据库表中,然后使用SQL将用户表加入列表,或者3)将列表加载到以逗号分隔的列表中字符串并使用SQL的IN运算符代替您的名字= x OR name = y OR name = z construct。

答案 2 :(得分:1)

如果要将列表传递给SQL Server 2008,请使用table-valued parameters。在数据库中,首先需要创建一个新的TYPE:

CREATE TYPE dbo.ListOfInt AS TABLE(Value INT);

然后您可以将其用作参数,例如:

var table = new DataTable();
table.Columns.Add("Value", typeof(int));

for (int i = 0; i < liste.Count; i++)
{
    var row = table.NewRow();
    row[0] = liste[i];
    table.Rows.Add(row);
}

string sql = "SELECT ID FROM [User] WHERE ID IN (SELECT Value FROM @Liste)";

using (var connection = new SqlConnection("Your connection String"))
using (var command = new SqlCommand(sql, connection))
{
    connection.Open();
    var tvp = new SqlParameter("@Liste", SqlDbType.Structured).TypeName = "ListOfInt";
    tvp.Value = table;
    command.Parameters.Add(tvp);
    using (var reader = command.ExecuteReader())
    while (reader.Read())
    {
        outliste.Add(reader.GetInt("ID"));
    }
}