从SQL Server中选择百万条记录

时间:2012-02-10 23:29:11

标签: c# asp.net sql-server sql-server-2008 sql-server-2005

我们需要索引(在ASP.NET中)存储在SQL Server表中的所有记录。该表有大约2M条记录,每行也包含文本(nvarchar)数据。

是否可以一次性获取所有记录,因为我们需要将它们编入索引(用于搜索)?另一种选择是什么(我想避免分页)?

注意:我没有显示这些记录,只需要一次性使用所有这些记录,以便我可以通过后台线程为它们编制索引。

我是否需要为查询设置任何长时间的输出?如果是,如果我从ASP.NET页面运行查询,那么设置更长时间的最有效方法是什么?

5 个答案:

答案 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;
}

<强>建议

  1. 最好从数据库级别过滤掉记录......
  2. 从数据库中提取所有记录并将其保存在文件中。访问该文件以进行任何中间操作。

答案 3 :(得分:0)

您在Extract Transform Load(ETL)中描述的内容。我知道有两个选项:

  1. SSIS是sql server的一部分
  2. Rhino.ETL
  3. 我更喜欢Rhino.Etl,因为它完全用C#编写,你可以在Boo中创建脚本,并且测试和编写ET​​L进程要容易得多。并且该库是为处理大量数据而构建的,因此内置了内存管理。

    最后一点说明:虽然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; }
}