当我尝试从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);
}
当我在我的测试数据库中尝试模拟这个时,我对搜索(相同)句子没有任何问题。
你有什么提示吗?
我无法对用户数据表做任何更改,我不能去找他并检查会发生什么。
答案 0 :(得分:1)
SQL命令是否正在执行存储过程?如果是这样,您可能会得到不同的查询计划,这可以解释应用程序之间的时间差异。您的ADO.Net调用可能会受到parameter sniffing的影响,这会导致查询执行时间完全不同。
您可以采取一些措施来避免此问题并产生一致的结果。
John也指出,你的语法看起来很可疑。最好对该列使用NVARCHAR(MAX)数据类型,如果可能的话,应该避免使用NTEXT,因为它已被弃用。
对像这样的非索引列进行搜索的更好的替代方法是利用SQL的全文搜索,该搜索针对这些类型的查询进行了优化。
答案 1 :(得分:1)
您可能想要做的一些事情。
首先,不要使用nText。 SQL 2005有一个名为nvarchar(max)的数据类型。存储大量文本更好。此外,ntext已被弃用,因此请省去一些麻烦并立即转换它。有关如何成功执行此操作,请参阅this link。
其次,您发布的查询不常见。您有一个左外连接,但外连接表上有一个where子句。由于where子句,它被转换(希望)为内连接。你应该这样写它或移动au.au_type = 11成为join结构的一部分。我怀疑你想要后者。
第三,当客户端第一次通过您的应用程序运行查询时,它会根据这些参数生成查询计划。此后不久在Management Studio中运行完全相同的查询将重用该计划和缓存数据。因此第二次传球会很快,所以不会感到惊讶。
第四,我认为您没有发布已运行的实际查询。我怀疑你要比较的参数中有一些数据要么没有正确转义,要么使用其中一个保留字符,如'[',']',^等。