Ich habe eine SQL-Tabelle Accounts in SQL Server, wo Daten in Bezug auf Datum sortiert ist. Die Tabelle enthält 20 Spalten einschließlich AccountId
.
Ich möchte die Datensätze für jeden Tag (Rund 200K Datensätze) lesen. Auf diese Weise müsste ich die Daten von 6 Monaten für jeden Tag lesen.So lesen Sie eine große Anzahl von Datensätzen aus SQL-Tabelle in Stapeln mit Task Parallele Bibliothek
Was ich tun muss, ist Datensätze aus Accounts Tabelle für 6 Monate Daten abzurufen. Also plante ich meinen Code, um die Daten von SQL Server Accounts
Tabelle innerhalb einer Do While-Schleife für jeden Tag zu bekommen.
Jetzt besteht jeder Tag aus dem Abrufen von 200K-Datensätzen aus der Datenbank. Also breche ich diese 200K-Datensätze für einen Tag in Chargen (sagen wir 10000 oder 20000 Datensätze in einem Lesevorgang, was ungefähr 10 Chargen von Datensätzen für einen Tag ergibt). Sobald ich diese 10k oder 20k Datensätze bekomme, möchte ich diese Werte aus der Datenbank holen und diese in eine CSV-Datei konvertieren und die CSV-Datei an einen Ort exportieren.
Jetzt ist mein Problem, dass diese Prozedur zu viel Zeit in Anspruch nimmt (ca. 50 Minuten für das Abrufen von Datensätzen für einen Tag und ich muss die Datensätze für 6 Monate Daten abrufen. So können Sie sich vorstellen, wie viel Zeit es dauern wird).
Ich denke, TPL verwenden, um den Code und die Verarbeitung in Aufgaben zu brechen, aber nicht sicher, wie es geht.
Bitte schlagen Sie vor, wie verwende ich Task parallele Bibliothek, um die Leistung zu verbessern, so dass ich leicht 6 Monate Daten erhalten kann.
My C# Code sieht wie folgt:
public void Main()
{
do
{
done = true;
var accountsTableRecors = ReadsDatabaseForADay(lastId);
foreach (var accountsHistory in accountsTableRecors)
{
if (accountsHistory.accountsId != null) lastId = (long)accountsHistory.accountsId;
done = false;
recordCount++;
}
var flatFileDataList = ProcessRecords();
} while (!done);
}
ProcessRecords
Das obige Verfahren in Main()
parst einige XML konvertiert und an abgerufenen Daten in CSV.
private IEnumerable<AccountsTable> ReadsDatabaseForADay(long lastId)
{
var transactionDataRecords = DatabaseHelper.GetTransactions(lastId, 10000);
var accountsTableData = transactionDataRecords as IList<AccountsTable> ?? transactionDataRecords.ToList();
ListAccountsTable.AddRange(accountsTableData);
return accountsTableData;
}
DatabaseHelperClass
:
internal static IEnumerable<AccountsTable> GetTransactions(long lastTransactionId, int count)
{
const string sql = "SELECT TOP(@count) [accounts_id],[some_columns],[some_other_columns]. .....[all_other_columns] "
+ "FROM AccountsTable WHERE [accounts_id] > @LastTransactionId AND [creation_dt] > DATEADD(DAY,-1, GETDATE())" +
" ORDER BY [accounts_id]";
return GetData(connection =>
{
var command = new SqlCommand(sql, connection);
command.Parameters.AddWithValue("@count", count);
command.Parameters.AddWithValue("@LastTransactionId", lastTransactionId);
return command;
}, DataRecordToTransactionHistory);
}
private static IEnumerable<T> GetData<T>(Func<SqlConnection, SqlCommand> commandBuilder, Func<IDataRecord, T> dataFunc)
{
using (var connection = GetOpenConnection())
{
using (var command = commandBuilder(connection))
{
command.CommandTimeout = 0;
using (IDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
var record = dataFunc(reader);
yield return record;
}
}
}
}
}
Sollten Sie dies nicht mit etwas wie SSIS anstelle von Code tun? Das Verwenden von Tasks löst das Problem möglicherweise nicht, da Sie den Server möglicherweise überlasten. Sind Sie nach unten gegangen, um zu sehen, ob die Abfragen mithilfe von Indizes usw. optimiert sind? Oder können Sie den Export in CSV auf eine ganz andere Art und Weise angehen? –
Sicher sollte ich Peter, aber hier ist das Problem zweifach. Die Daten befinden sich auf dem Produktionsserver, auf den ich keinen direkten Zugriff habe, und zweitens gibt es viele Spalten, die nach dem Abrufen eine Datenmanipulation benötigen. Daher wählte ich den Code Weg –
Holen 200k Zeilen sollte Sekunden dauern nicht eine Stunde, so dass Sie das Problem beheben müssen, bevor Sie beginnen, TPL zu werfen. – Phil