【问题标题】:Searching SQL Server with LIKE Operator使用 LIKE 运算符搜索 SQL Server
【发布时间】:2010-12-28 17:16:14
【问题描述】:

当我尝试从 C# 代码中读取 SQL Server 2005 中的行时遇到问题

想法:

在我的数据库 (SQL Server 2005 Express) 中有一个表,其中有一列(数据类型为 ntext)包含 HTML 代码。

在我的 C# 应用程序中,用户可以输入一个句子(HTML 代码)并搜索包含该句子的行。

我的应用生成的查询是:

USE test   
SELECT   
 al.aal_Id As ID,   
 al.aal_Description As Opis,   
 au.au_Title As Tytul_szablonu,   
 au.au_Note As Nazwa_szablonu   
FROM dbo.au_Allegro al   
LEFT OUTER JOIN dbo.au__Auction au ON (al.aal_AuctionId = au.au_Id)   
WHERE  
 au.au_Type = 11   
 AND al.aal_Description COLLATE SQL_Latin1_General_CP1_CS_AS LIKE '%%' ESCAPE '\'  

在我的应用程序中,我正在转换特殊字符(例如 ',)并添加转义字符。

用户尝试搜索很长的句子(大约 7000 多个字符),当他尝试这样做时,sqlserver.exe 进程消耗了他所有的 RAM 内存,搜索时间大约是 30 多分钟(他有大约 1000 多行在此表中)。

查询返回 0 行。

当他尝试在 SQL Server Management Studio 中运行(同样的)查询时,数据库会在几秒钟内显示结果(有行)。

在我的应用中,我使用SqlDataAdapter

System.Data.DataTable dt = new System.Data.DataTable();  
System.Data.SqlClient.SqlCommand cmd = new System.Data.SqlClient.SqlCommand();  
cmd.CommandTimeout = 0;  
cmd.Connection = conn;  
System.Data.SqlClient.SqlDataAdapter da = new System.Data.SqlClient.SqlDataAdapter(kwerenda, conn);  
try  
{
  da.Fill(dt);
}

我试过SqlDataReader

dr = cmd.ExecuteReader();  
while (dr.Read())  
{  
  string id = dr["ID"].ToString();  
  string opis = dr["Opis"].ToString();  
  string tytul = dr["Tytul_szablonu"].ToString();  
  string nazwa = dr["Nazwa_szablonu"].ToString();  
  dt.Rows.Add(id, opis, tytul, nazwa);  
}

当我尝试在我的测试数据库中模拟这一点时,我在搜索(同样的)句子方面没有任何问题。

你有什么建议吗?

我无法对用户数据表进行任何更改,我无法去找他检查发生了什么。

【问题讨论】:

  • LIKE '%%' 不会匹配所有行吗?
  • @John Saunders:这将匹配所有行并且这样做没有索引的任何好处。此外,它将检查每一行中的每个字符,只返回所有字符。我猜查询时间与存储的数据量有关。
  • @Chris:将ntext 添加到该等式中,我认为我们已经赢了。
  • @Chris:我无法更改列类型,我正在其他应用程序数据库中搜索(我的应用程序不是该数据库的所有者)
  • @user:请编辑您问题中的查询以更接近现实。如果您实际上不搜索%%,那么为什么告诉我们您搜索过?

标签: c# sql sql-like


【解决方案1】:

SQL 命令是否执行存储过程?如果是这样,您可能会得到不同的查询计划,这可以解释应用程序之间的时间差异。您的 ADO.Net 调用可能会受到 parameter sniffing 的影响,这会导致查询执行时间完全不同。

您可以采取一些措施来避免此问题并产生一致的结果

  1. 将参数转换为存储过程中的局部变量。
  2. 完全禁用 SQL 服务器上的功能。

正如约翰指出的那样,您的语法看起来也很可疑。如果可能的话,最好为该列使用 NVARCHAR(MAX) 数据类型,因为 NTEXT 已被弃用。

在这样的非索引列上进行类似搜索的更好替代方法是利用 SQL 的全文搜索,该搜索针对这些类型的查询进行了优化。

【讨论】:

  • +1。但是,我的全文搜索的查询时间结果不一致。有时它非常快,有时它非常慢。相同的应用,不同的表格,几乎完全相同的结构,当然还有相同的 fts 设置。
【解决方案2】:

您可能想做的几件事。

首先,不要使用 nText。 SQL 2005 有一个名为 nvarchar(max) 的数据类型。存储大量文本要好得多。此外,ntext 已被弃用,因此您可以省去一些麻烦并立即进行转换。请参阅this link,了解如何成功完成此操作。

其次,您发布的查询不寻常。您有一个左外连接,但在外连接表上有一个 where 子句。由于 where 子句,它被(希望)转换为内部连接。你应该这样写或者移动 au.au_type = 11 成为连接结构的一部分。我怀疑你想要后者。

第三,当客户端第一次通过您的应用运行查询时,它会根据这些参数生成查询计划。此后不久在 Management Studio 中运行完全相同的查询将重用该计划和缓存的数据。因此第二遍会很快,所以这并不奇怪。

第四,我认为您没有发布实际运行的查询。我怀疑您正在比较的参数中有一些数据没有正确转义,或者正在使用保留字符之一,例如“[”、“]”、^ 等。

【讨论】:

    猜你喜欢
    • 2011-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-02
    • 1970-01-01
    • 1970-01-01
    • 2016-12-24
    • 1970-01-01
    相关资源
    最近更新 更多