我有大約700K行正在迭代。對於每一行,都會在數據庫上運行一條SELECT sql語句,以檢查當前記錄中的「名稱」字段是否存在於相應的表中。查詢數據庫的每條記錄比使用LINQ更快
700K次的數據庫讀取效率非常低,所以我選擇在循環前讀取所有數據,將其存儲在DataTable中,並檢查相應的記錄是否通過LINQ包含在DataTable中,on每次迭代。
在做到這一點時,性能下降了不少。這個過程大約需要兩倍的時間才能完成(通過基準測試多次證明)。
這是原來的(快)代碼:
for (int index = 0; index < dtSightings.Rows.Count; index++)
{
DataTable dtResults = Utilities.ExecuteQueryMysqlString(connectionString, "SELECT name FROM my_table WHERE name = @name AND month_year = @monthYear", dictionary);
if (dtResults == null || dtResults.Rows.Count == 0)
{
//Continue
}
}
public static DataTable ExecuteQueryMysqlString(string connectionString, string sql, Dictionary<string, object> listParameters)
{
DataTable dtResults = new DataTable();
if (string.IsNullOrWhiteSpace(connectionString) == false)
{
connectionString += ";Allow User Variables=True;";
try
{
using (MySqlConnection connection = new MySqlConnection(connectionString))
{
connection.Open();
using (MySqlCommand cmd = connection.CreateCommand())
{
cmd.CommandTimeout = 0;
cmd.CommandText = sql;
if (listParameters != null && listParameters.Count > 0)
{
foreach (string currentKey in listParameters.Keys)
{
cmd.Parameters.Add(new MySqlParameter(currentKey, GetDictionaryValue(listParameters, currentKey)));
}
}
using (MySqlDataAdapter da = new MySqlDataAdapter(cmd))
{
da.Fill(dtResults);
}
}
}
return dtResults;
}
catch (Exception ex)
{
MessageBox.Show("ERROR: " + ex.Message, "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
return dtResults;
}
}
else
{
return dtResults;
}
}
這是 「優化」(但速度較慢)代碼:
DataTable dt= Utilities.ExecuteQueryMysqlString(connectionString, "SELECT name, month_year FROM my_table", null);
for (int index = 0; index < dtSightings.Rows.Count; index++)
{
DataRow row = dt.AsEnumerable().Where(r => r.Field<string>("name").Equals(name, StringComparison.InvariantCultureIgnoreCase) && r.Field<DateTime>("month_year") == new DateTime(billYear, billMonth, 1)).FirstOrDefault();
if (hasResidentBeenDiscoveredPreviously == null)
{
//Continue
}
}
我不明白爲什麼第一種方法速度非常快。有沒有更好的方法來取代第二種方法?
它看起來像你're cross ref在同一個數據庫中創建兩個表,爲什麼不讓SQL處理這個工作並讓它返回一個不在任何表中的記錄列表。一個「左連接」或「不存在的地方」會創造奇蹟。 – jessehouwing
實際上只有一個表 - 「my_table」 –
如果需要,您可以將表加入自己。 – jessehouwing