提高从SQL Server返回数据时的性能
本文关键字:数据 性能 返回 Server SQL | 更新日期: 2023-09-27 18:15:06
我在SQL Server Management Studio中有一个存储过程,在大约10秒内产生2,675条记录。
然而,当我从我的c#应用程序调用它时,需要1:05来填充DataTable
。我能做些什么来提高表现吗?
下面是我如何填充DataTable
:
public static DataTable GetDataTable(string procName, params SqlParameter[] procParams)
{
using (_conn = new SqlConnection(_connStr))
{
SqlCommand cmd = _conn.CreateCommand();
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = procName;
if (procParams != null)
{
foreach (SqlParameter p in procParams)
{
cmd.Parameters.Add(p);
}
}
_conn.Open();
var da = new SqlDataAdapter(cmd);
var table = new DataTable();
da.Fill(table);
return table;
}
}
特别在这一点上:
var table = new DataTable();
da.Fill(table);
几乎所有的时间都被占用了(大约60秒)。
我以前用这种方法处理过大数据,从来没有遇到过这么大的延迟。
有什么建议或想法吗?
更新:
我们还尝试了这样的DataReader
:
var dataReader = cmd.ExecuteReader();
table.Load(dataReader);
dataReader.Close();
更新:
在桌面报表查看器中为相同的报表运行相同的sp,可以在12秒内获得结果。这是在网页和桌面上运行的相同的报告。为什么这么慢?
叫SP:
这是SP运行为报告获取数据。
ALTER PROCEDURE [dbo].[rptCheckRegDetail]
@ldStartDt as char(10) = '',
@ldEndDt as char(10) = '',
@lcStartCkNo as char(10)= ' ',
@lcEndCkNo as char(10) =' ',
@lcUniqSupNo as char(10)=' ',
@lcBk_Uniq as char(10)= ' ',
@lnStatus as int=1
as
begin
declare @ChkHd table (ApChk_uniq char(10),Bank char(35),Bk_acct_no char(15),
iCheckno char(10),Checkno char(10),CheckDate smalldatetime,
SupName char(35),CheckAmt numeric(12,2),Status char(15), Detail char(6),
CheckNote text,ReconcileStatus char(1),ReconciledDate smalldatetime)
Insert into @ChkHd
exec [CheckRegView] @ldStartDt,@ldEndDt,@lcStartCkNo,@lcEndCkNo,@lcUniqSupNo,@lcBk_Uniq,@lnStatus
SELECT c1.ApChk_uniq, c1.Bank, c1.Bk_acct_no, c1.iCheckno, c1.Checkno,
c1.CheckDate, c1.SupName,
case when
ROW_NUMBER() over (partition by c1.apchk_uniq order by c1.checkno) = 1
then CheckAmt else cast(0.00 as numeric(12,2)) end as CheckAmt,
c1.status,c1.checknote,Apchkdet.item_no, Apchkdet.ponum, Apchkdet.invno,
Apchkdet.invdate, Apchkdet.due_date, Apchkdet.item_desc, Apchkdet.invamount,
Apchkdet.disc_tkn, Apchkdet.aprpay,Apchkdet.apchk_uniq, Apchkdet.itemnote,
MICSSYS.LIC_NAME
FROM @ChkHd as C1
inner join apchkdet on apchkdet.APCHK_UNIQ = c1.ApChk_uniq
cross join micssys
ORDER BY Checkno,Apchkdet.item_no
end
SqlDataAdapter
在创建DataTable
时天生很慢。因为查询在SSMS中执行得相对较快,所以DataTable
的填充可能是主要问题。
如果你所做的只是读取数据并在其他地方列出它,那么使用SqlDataReader
创建Dictionary<string, object>
列表会更有效。
你的方法可以这样替换:
public static List<Dictionary<string, object>> GetDataTable(string procName, params SqlParameter[] procParams)
{
using (_conn = new SqlConnection(_connStr))
{
using (SqlCommand cmd = _conn.CreateCommand())
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = procName;
if (procParams != null)
{
foreach (SqlParameter p in procParams)
{
cmd.Parameters.Add(p);
}
}
_conn.Open();
using (var reader = cmd.ExecuteReader())
{
var result = new List<Dictionary<string, object>>();
while (reader.Read())
{
var row = new Dictionary<string, object>();
for (int i = 0; i < reader.FieldCount; i++)
{
string fieldName = reader.GetName(i);
row.Add(fieldName, reader[fieldName]);
}
result.Add(row);
}
return result;
}
}
}
}
我还没有测试这段代码,但它应该几乎可以工作!:)
然后可以像这样遍历行:
foreach (var result in results)
{
foreach (KeyValuePair<string, object> field in result)
{
string fieldName = field.Key;
string fieldValue = field.Value.ToString(); // Cast to correct type here
}
}
我有同样的问题,这是我发现的。SQLDataAdapter显然在SmallDateTime变量方面存在问题。将SmallDateTime转换为一个普通的DateTime,它应该会加快DataReader的速度。
那么,按如下方式强制转换smalldatetime sql:
Cast(@smalldatetimevar as datetime) smalldatetimevar
当我在我的项目中这样做时,table.Load(dataReader)命令从超时变为立即返回结果集。
查看是应用程序慢还是SQL Server慢,使用SQL Profiler跟踪执行的查询。