我们需要索引(在ASP.NET中)存储在SQL Server表中的所有记录。该表有大约2M条记录,每行也包含文本(nvarchar)数据。
是否可以一次性获取所有记录,因为我们需要将它们编入索引(用于搜索)?另一种选择是什么(我想避免分页)?
注意:我没有显示这些记录,只需要一次性使用所有这些记录,以便我可以通过后台线程为它们编制索引。
我是否需要为查询设置任何长时间的输出?如果是,如果我从ASP.NET页面运行查询,那么设置更长时间的最有效方法是什么?
答案 0 :(得分:1)
如果我需要这样的东西,只是从数据库方面考虑它,我可能会把它导出到一个文件。然后该文件可以很容易地移动。移动数据集对所有参与者来说都是一个巨大的痛苦。您可以在批处理命令中使用SSIS,sqlcmd甚至bcp来完成它。
然后,你只需要担心你在应用程序端使用它做什么,不用担心锁定&导出后,数据库端的所有内容。
答案 1 :(得分:0)
我认为页面不是一个好地方。应该有一个不同的流程或程序来执行此操作。在相关的说明中,像http://incubator.apache.org/lucene.net/这样的东西会对你有帮助吗?
答案 2 :(得分:0)
可以一次性获取所有记录,因为我们需要索引它们 (搜索)?另一种选择是什么(我想避免分页)?
内存管理问题/性能问题
如果您带来了2百万条记录,您可能会面临系统内存异常 因为您将在DataSet中保留所有这些记录,并且数据集内存将在RAM中。
我是否需要为查询设置任何长时间的输出?如果是,那是什么 如果我正在运行,那么设置更长时间的最有效方法 从ASP.NET页面查询?
using (System.Data.SqlClient.SqlCommand cmd = new System.Data.SqlClient.SqlCommand())
{
cmd.CommandTimeout = 0;
}
<强>建议强>
答案 3 :(得分:0)
您在Extract Transform Load(ETL)中描述的内容。我知道有两个选项:
我更喜欢Rhino.Etl,因为它完全用C#编写,你可以在Boo中创建脚本,并且测试和编写ETL进程要容易得多。并且该库是为处理大量数据而构建的,因此内置了内存管理。
最后一点说明:虽然asp.net可能是启动索引过程的入口点,但我不会在asp.net中运行该过程,因为它可能需要几分钟或几小时,具体取决于记录和处理量。 / p>
而是让asp.net成为触发后台任务来处理记录的入口点。理想情况下,完全独立于asp.net,因此您可以避免任何超时或关机问题。
答案 4 :(得分:0)
批量处理您的记录。你将有两个主要问题。 (1)您需要索引所有现有记录。 (2)您将要使用添加,更新或删除的记录更新索引。听起来只是为了删除索引并重新创建它,但如果可能的话应该避免使用它。以下是以10,000个记录批量处理[Production].[TransactionHistory]
数据库中的AdventureWorks2008R2
的示例。它不会将所有记录加载到内存中。我本地计算机上的输出产生Processed 113443 records in 00:00:00.2282294
。显然,这并没有考虑到每条记录的远程计算机和处理时间。
class Program
{
private static string ConnectionString
{
get { return ConfigurationManager.ConnectionStrings["db"].ConnectionString; }
}
static void Main(string[] args)
{
int recordCount = 0;
int lastId = -1;
bool done = false;
Stopwatch timer = Stopwatch.StartNew();
do
{
done = true;
IEnumerable<TransactionHistory> transactionDataRecords = GetTransactions(lastId, 10000);
foreach (TransactionHistory transactionHistory in transactionDataRecords)
{
lastId = transactionHistory.TransactionId;
done = false;
recordCount++;
}
} while (!done);
timer.Stop();
Console.WriteLine("Processed {0} records in {1}", recordCount, timer.Elapsed);
}
/// Get a new open connection
private static SqlConnection GetOpenConnection()
{
SqlConnection connection = new SqlConnection(ConnectionString);
connection.Open();
return connection;
}
private static IEnumerable<TransactionHistory> GetTransactions(int lastTransactionId, int count)
{
const string sql = "SELECT TOP(@count) [TransactionID],[TransactionDate],[TransactionType] FROM [Production].[TransactionHistory] WHERE [TransactionID] > @LastTransactionId ORDER BY [TransactionID]";
return GetData<TransactionHistory>((connection) =>
{
SqlCommand command = new SqlCommand(sql, connection);
command.Parameters.AddWithValue("@count", count);
command.Parameters.AddWithValue("@LastTransactionId", lastTransactionId);
return command;
}, DataRecordToTransactionHistory);
}
// funtion to convert a data record to the TransactionHistory object
private static TransactionHistory DataRecordToTransactionHistory(IDataRecord record)
{
TransactionHistory transactionHistory = new TransactionHistory();
transactionHistory.TransactionId = record.GetInt32(0);
transactionHistory.TransactionDate = record.GetDateTime(1);
transactionHistory.TransactionType = record.GetString(2);
return transactionHistory;
}
private static IEnumerable<T> GetData<T>(Func<SqlConnection, SqlCommand> commandBuilder, Func<IDataRecord, T> dataFunc)
{
using (SqlConnection connection = GetOpenConnection())
{
using (SqlCommand command = commandBuilder(connection))
{
using (IDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
T record = dataFunc(reader);
yield return record;
}
}
}
}
}
}
public class TransactionHistory
{
public int TransactionId { get; set; }
public DateTime TransactionDate { get; set; }
public string TransactionType { get; set; }
}