Обход таблицы базы данных при малой памяти - PullRequest
1 голос
/ 20 марта 2012

У меня есть база данных с большим количеством записей с отметкой даты / времени. Мне нужно просмотреть эти записи (в хронологическом порядке) и проанализировать их.

База данных слишком велика, чтобы загружать каждую запись одновременно, поэтому я подумал о том, чтобы загружать по несколько недель / дней / часов / и т. Д. Одновременно. Проблема в том, что независимо от того, что я пробовал, база данных (SQL Server) просто использует всю память на моем компьютере. Даже после закрытия приложения sqlservr.exe все еще использует всю мою память. Обычно он использует около 1,8 ГБ памяти, независимо от того, содержат ли мои «партии» только 10 записей или 1 000 000.

Вопрос заключается в следующем: как я могу запросить базу данных, чтобы получить «партии» записей за раз, без использования базой данных каждого бита памяти?

Я использую библиотеки System.Data.SqlClient. Вот немного псевдокода:

String file = "C:\\db.mdf";
String connString = @"Data Source=.\SQLExpress;AttachDbFilename="C:\db.mdf";Integrated Security=True;User Instance=True";

SqlConnection conn = new SqlConnection(connString);
conn.Open();

DateTime start = DateTime.MinValue;
DateTime end = DateTime.MaxValue;

while()
{
   // This should query for 1 hour at a time (but I should be able to change the time interval)
   // I would like for the memory usage to be proportional to the time interval

   String query = "SELECT * From MyTable WHERE Date BETWEEN '" + start.ToString() + "' AND '" + end.ToString() + "'";
   SqlCommand cmd = new SqlCommand(query, conn);
   SqlDataReader reader = command.ExecuteReader();

   while(reader.Read())
      ProcessRecord(ref reader);

   start = end;
   end = end.AddHours(1);
}

conn.Close();

C #
.NET 3.5
SQL Server 2008

Спасибо.

Ответы [ 3 ]

4 голосов
/ 20 марта 2012

Это нормально, SQL Server будет использовать всю доступную память , если не настроено иначе .

Sql Server Express освободит память, когда другие приложения будут запрашивать больше, но попытается использовать всю память для кэширования планов и данных запросов.

Цитата из связанной статьи:

В следующем примере для параметра max server memory установлено значение 4 ГБ:

 exec sp_configure 'show advanced options', 1; 
 GO 
 RECONFIGURE; 
 GO
 exec sp_configure 'max server memory', 4096; 
 GO 
 RECONFIGURE; 
 GO
 exec sp_configure 'show advanced options', 0;
 RECONFIGURE;  
 GO 

Обратите внимание на то, что SqlConnection, SqlCommand и SqlDataReader реализуют IDisposable, поэтому вы обычно захотите заключить их в предложение using.

2 голосов
/ 20 марта 2012

Ответ Филипа правильный, именно так SQL Server настроен на поведение.

Причина, по которой это значение по умолчанию, обычно заключается в том, что серверы баз данных работают на выделенном компьютере, на котором почти ничего не работает, кроме базы данных, и проблема № 1 - это скорость базы данных. Обычно вы хотите хранить как можно больше в памяти, чтобы минимизировать частоту попадания на диск.

В качестве альтернативы программной настройке параметра вы можете использовать Sql Server Management Studio (SSMS) для изменения конфигурации. Подключитесь к вашей базе данных, щелкните по ней правой кнопкой мыши и перейдите в Свойства. На странице Память вы можете настроить максимальный объем памяти, который будет использовать база данных.

1 голос
/ 20 марта 2012

A SqlDataReader будет передавать результаты. Пока вы не удерживаете данные, возвращаемые записью из считывателя, сборщик мусора .NET будет собирать все эти данные (в неопределенное время). Другими словами, ваш while(reader.Read()) ProcessRecord(reader); будет работать просто отлично. .NET не будет загружать полный набор в память (если вы не сделаете это явно, например, используя DataSet или DataTable).

...