C# 优化LINQ查找查询
我正在编写一个报告,它需要来自两个不同位置的数据,一个是SQL Server数据库,另一个是DB2数据库,我用下面的代码完成了这项工作 这是我的SQL Server数据库:C# 优化LINQ查找查询,c#,sql,performance,linq,query-optimization,C#,Sql,Performance,Linq,Query Optimization,我正在编写一个报告,它需要来自两个不同位置的数据,一个是SQL Server数据库,另一个是DB2数据库,我用下面的代码完成了这项工作 这是我的SQL Server数据库: private List<MerchantTerminal> GetListOfActiveTerminals(Int64 corebankingRecord, Int64 terminalRecord, bool dialup, bool ethernet, bool cellular, bool wifi,
private List<MerchantTerminal> GetListOfActiveTerminals(Int64 corebankingRecord, Int64 terminalRecord, bool dialup, bool ethernet, bool cellular, bool wifi, bool merchantAdviceBypass, bool merchantRefundBypass, bool authAdviceOnly)
{
StringBuilder sql = new StringBuilder();
sql.Append("Select distinct ");
sql.Append(" POSH5_Prod_MerchantTerminalDetails.id ");
sql.Append(", POSH5_Prod_MerchantTerminalDetails.merchantRecord ");
sql.Append(", POSH5_Prod_MerchantTerminalDetails.terminalID ");
sql.Append(", POSH5_Prod_MerchantTerminalDetails.TerminalRecord ");
sql.Append(", POSH5_Prod_MerchantTerminalDetails.MCCRecord ");
sql.Append(", POSH5_Prod_MerchantTerminalDetails.PINPadRecord ");
sql.Append(", POSH5_Prod_MerchantTerminalDetails.terminalRentalFee ");
sql.Append(", POSH5_Prod_MerchantTerminalDetails.terminalRentalFeeCurrencyRecord ");
sql.Append(", POSH5_Prod_MerchantTerminalDetails.DialUp ");
sql.Append(", POSH5_Prod_MerchantTerminalDetails.Ethernet ");
sql.Append(", POSH5_Prod_MerchantTerminalDetails.WiFi ");
sql.Append(", POSH5_Prod_MerchantTerminalDetails.GPRS ");
sql.Append(", POSH5_Prod_MerchantTerminalDetails.Internet ");
sql.Append(", POSH5_Prod_MerchantTerminalDetails.PrimaryCurrencyRecord ");
sql.Append(", POSH5_Prod_MerchantTerminalDetails.SecondaryCurrencyRecord ");
sql.Append(", POSH5_Prod_MerchantTerminalDetails.TIP ");
sql.Append(", POSH5_Prod_MerchantTerminalDetails.AllowManuallyKeyedTransactions ");
sql.Append(", POSH5_Prod_MerchantTerminalDetails.MinimumTransactionVolume ");
sql.Append(", POSH5_Prod_MerchantTerminalDetails.MinimumTransactionVolumeCurrencyRecordID ");
sql.Append(", POSH5_Prod_MerchantTerminalDetails.MinimumTransactionVolumeFee ");
sql.Append(", POSH5_Prod_MerchantTerminalDetails.MinimumTransactionVolumeFeeCurrencyRecordID ");
sql.Append(", POSH5_Prod_MerchantDetails.bypassAdviceVerification ");
sql.Append(", POSH5_Prod_MerchantDetails.bypassCreditVerification ");
sql.Append(", POSH5_Prod_MerchantDetails.expireBypassCreditDate ");
sql.Append("from POSH5_Prod_MerchantTerminalDetails ");
sql.Append("left join POSH5_Prod_MerchantDetails on POSH5_Prod_MerchantTerminalDetails.merchantRecord = POSH5_Prod_MerchantDetails.id ");
sql.Append("where POSH5_Prod_MerchantTerminalDetails.active=@active ");
sql.Append("and POSH5_Prod_MerchantDetails.corebankingRecord=@corebankingRecord ");
//if (merchantAdviceBypass == true)
//{
// sql.Append("and POSH5_Prod_MerchantDetails.bypassAdviceVerification=@merchantadvicebypass ");
//}
//else
//{
// sql.Append("and POSH5_Prod_MerchantDetails.bypassAdviceVerification = 1 OR POSH5_Prod_MerchantDetails.bypassAdviceVerification = 0 ");
//}
//if (merchantRefundBypass == true)
//{
// sql.Append("and POSH5_Prod_MerchantDetails.bypassCreditVerification=@merchantrefundbypass ");
//}
//else
//{
// sql.Append("and POSH5_Prod_MerchantDetails.bypassCreditVerification = 1 OR POSH5_Prod_MerchantDetails.bypassCreditVerification = 0 ");
//}
if (terminalRecord > 0)
{
sql.Append("and terminalRecord=@terminalRecord ");
}
sql.Append("AND (");
bool addedCommMethod = false;
if (dialup)
{
sql.Append("POSH5_Prod_MerchantTerminalDetails.DialUp=1 ");
addedCommMethod = true;
}
if (ethernet)
{
if (addedCommMethod)
{
sql.Append("OR ");
}
sql.Append("POSH5_Prod_MerchantTerminalDetails.Ethernet=1 ");
addedCommMethod = true;
}
if (cellular)
{
if (addedCommMethod)
{
sql.Append("OR ");
}
sql.Append("POSH5_Prod_MerchantTerminalDetails.GPRS=1 ");
addedCommMethod = true;
}
if (wifi)
{
if (addedCommMethod)
{
sql.Append("OR ");
}
sql.Append("POSH5_Prod_MerchantTerminalDetails.WiFi=1 ");
addedCommMethod = true;
}
sql.Append(") ");
sql.Append("order by terminalID; ");
var merchantTerminalRecordList = new List<MerchantTerminal>();
var serialnumberlist = PopulateSerialNumberList();
using (SqlConnection connectionMSW = new SqlConnection(_connectionString))
{
connectionMSW.Open();
SqlCommand commandMSW = new SqlCommand();
commandMSW.CommandTimeout = 600;
commandMSW.CommandText = sql.ToString();
commandMSW.Connection = connectionMSW;
commandMSW.Parameters.AddWithValue("@terminalRecord", terminalRecord);
commandMSW.Parameters.AddWithValue("@active", true);
commandMSW.Parameters.AddWithValue("@corebankingRecord", corebankingRecord);
commandMSW.Parameters.AddWithValue("@merchantadvicebypass", merchantAdviceBypass);
commandMSW.Parameters.AddWithValue("@merchantrefundbypass", merchantRefundBypass);
using (SqlDataReader reader = commandMSW.ExecuteReader())
{
while (reader.Read())
{
merchantTerminalRecordList.Add(PopulateMerchantTerminalRecord(reader, serialnumberlist));
}
}
}
return merchantTerminalRecordList;
}
private POSHData PopulateSerialNumberList()
{
POSHData result = new POSHData();
List<POSHSerialNumber> serialResults = new List<POSHSerialNumber>();
StringBuilder sql = new StringBuilder();
sql.Append("select distinct termcert.termid, termcert.termserno, termcert.PPADSERNO, termcert.appname, termcert.appversion, terminal.TERMTYPE, terminal.PINPADID, terminal.LASTTRAN, terminal.EDCCRSRC, termcfg.tranauthonly, termcfg.tranadjust from posh.termcert as termcert LEFT JOIN posh.terminal as terminal ON termcert.termid = terminal.termid LEFT JOIN posh.termcfg as termcfg ON termcert.termid = termcfg.termid");
DataSet dsResult = new DataSet();
using (DB2Connection connectionPOSH = new DB2Connection(_connectionStringPOSH))
{
connectionPOSH.Open();
DB2Command commandMSW = new DB2Command();
commandMSW.CommandTimeout = 600;
commandMSW.CommandText = sql.ToString();
commandMSW.Connection = connectionPOSH;
DB2DataAdapter adapter = new DB2DataAdapter();
adapter.SelectCommand = commandMSW;
adapter.Fill(dsResult);
}
foreach (DataRow item in dsResult.Tables[0].Rows)
{
POSHSerialNumber found = new POSHSerialNumber();
found.termid = item["termid"].ToString().Trim();
found.terminalSerialNumber = item["termserno"].ToString().Trim();
found.pinPadSerialNumber = item["PPADSERNO"].ToString().Trim();
found.appName = item["appname"].ToString().Trim();
found.appVersion = item["appversion"].ToString().Trim();
found.terminalRecord = dataTypeConversion.ToInt64(item["TERMTYPE"].ToString().Trim());
var pinPadRecord = dataTypeConversion.ToInt64(item["PINPADID"].ToString().Trim());
if (pinPadRecord > 0)
{
found.pinPadRecord = pinPadRecord;
found.pinPadSerialNumber = item["PPADSERNO"].ToString().Trim();
}
var LastTransaction = dataTypeConversion.ToDouble(item["LASTTRAN"].ToString());
found.LastTransaction = commonController.UnixTimeStampToDateTime(LastTransaction);
found.SettlementType = item["EDCCRSRC"].ToString().Trim();
found.tranAuthOnly = item["tranauthonly"].ToString().Trim();
found.tranAdjust = item["tranadjust"].ToString().Trim();
serialResults.Add(found);
}
result.poshSerialNumbers = serialResults;
return result;
}
在只有500-1000条记录的开发和质量保证环境中,这似乎很好。在我的PROD环境中,它的速度要慢得多,因为我们要处理多达20k+的记录。目前在prod中提取此数据的最快方法是什么?它最多需要5-8分钟
谢谢你的帮助
编辑:在各自的数据库中运行我的查询后,看起来实际的速度减慢是在我使用的LINQ查询中,我想更好的问题是对于大量的数据,如何优化我的LINQ?我不认为在MS SQL部分,至少在您显示的部分,您读取数据的方式有任何基本错误。现在使用ORM是很常见的(简洁、实体框架),但它们不是必需的 拉取此数据的最快方法是查找速度较慢的内容 在db客户端(例如SQL Management Studio)中运行查询 如果速度慢,请修复SQL
- 例如,该表可能缺少索引
- 数据库可能因为其他查询而忙
- 添加带有计时的日志(围绕重要部分(例如,围绕使用)的
),以便准确知道哪个部分速度慢。这可能不是数据库调用
POSHSerialNumber
对象时,您需要执行found.termid=item[“termid”].ToString().Trim();
,因此在使用Find
时无需再次执行此操作,可能与MerchantTerminal
相同,您可以避免使用Trim
这两种方法来构建查询!您可以对主节使用逐字字符串,使其更具可读性。和string.Join(…,,,,,,,,,)或
会很有用。想到的事情:1.考虑你需要哪些列和不需要哪些列2.合理地编制索引,特别是POSH5\u Prod\u merchantdetdetails
使用包含列,因为它只是几个列3.不要使用独立的,如果你不需要的话,考虑连接的作用4.不要使用顺序通过
,进行客户端排序。5.和
优先于或
,因此使用括号()
6.左连接没有任何意义,因为您稍后会在……….的一列上进行筛选。要么在上的中进行筛选,要么更改为内部连接
7。或
通常会影响性能,因为索引8很难使用。
private void GetSerialNumber(POSHData poshData, MerchantTerminal foundTerminal)
{
var result = poshData.poshSerialNumbers.Find(x => x.termid.Trim() == foundTerminal.terminalID.Trim());
if (result != null)
{
foundTerminal.terminalSerialNumber = result.terminalSerialNumber;
foundTerminal.pinPadSerialNumber = result.pinPadSerialNumber;
foundTerminal.appName = result.appName;
foundTerminal.appVersion = result.appVersion;
foundTerminal.pINPadRecord = result.pinPadRecord;
foundTerminal.terminalRecord = result.terminalRecord;
foundTerminal.LastTransactionDateTime = result.LastTransaction;
if (foundTerminal.pinPadSerialNumber.Length == 0)
{
foundTerminal.pinPadSerialNumber = result.pinPadSerialNumber;
}
switch (result.SettlementType)
{
case "2":
foundTerminal.PABX = "Journal";
break;
case "3":
foundTerminal.PABX = "Batch Close Required";
break;
default:
foundTerminal.PABX = "Unknown";
break;
}
foundTerminal.AdviceText = result.tranAdjust;
foundTerminal.AuthOnly = result.tranAuthOnly;
}