Как повысить производительность MS Access INSERT

У меня есть программа на C++, которая вставляет около миллиона записей в базу данных MS Access с помощью OLEDBConnection. Для этого я запускал запрос INSERT INTO миллионы раз, чтобы вставить записи, что занимает довольно много времени.

Данные генерируются в программе в виде массива. Будет ли это каким-либо другим способом загрузки данных в базу данных за один шаг для повышения производительности?

Спасибо!

Цикл, который я использую для вставки записей в настоящее время

for (int i = 0; i < populationSize; i++){
    insertSQL = "INSERT INTO [" + pTableName + "] (" + columnsName + ") VALUES (" + columnsValue[i] + ");";`
    outputDBConn->runSQLEdit(insertSQL);
}

Метод, выполняющий SQL-запрос

void DBConnector::runSQLEdit(String^ query){
    SQLCMD = gcnew OleDbCommand( query, dbConnection );
    SQLCMD->CommandTimeout = 30;
    dbConnection->Open();
    SQLCMD->ExecuteNonQuery();
    dbConnection->Close();
    }

person Raymond    schedule 22.12.2011    source источник
comment
MS Access и миллион записей не кажутся хорошей парой. Вы слышали о SQLite?   -  person ali_bahoo    schedule 22.12.2011
comment
Возможно, быстрее всего записать массив в CSV и загрузить его в Access за один шаг. Убедитесь, что у вас нет индексов в таблице, в которую вы загружаете данные.   -  person Fionnuala    schedule 22.12.2011


Ответы (2)


Кажется очень неэффективным открывать/закрывать соединение для каждого оператора вставки.

Стандартный подход выглядит примерно так:

  1. Открытое соединение.
  2. Начать транзакцию, если поддерживается. (Это часто очень важно для баз данных с транзакциями.)
  3. Вставлять. Повторяйте этот шаг по мере необходимости.
  4. Зафиксировать транзакцию, если поддерживается.
  5. Закрыть соединение.

Обновление: следующее не относится к MS Access. Доступ не поддерживает вставку нескольких строк < em>из литерала. Он поддерживает только вставку нескольких строк из существующего источника данных. (Хотя вот " workabout", который может сработать. В любом случае, самое главное, вероятно, ограничить количество транзакций.)

Еще одна вещь, которую можно сделать, — это создать одну команду вставки, которая одновременно добавляет несколько записей. Это можно сделать либо с помощью нескольких операторов, либо с помощью вставки нескольких записей (если поддерживается). Это может быть или не быть значительно быстрее, чем просто выше (зависит от других факторов, таких как сетевая задержка и механизм базы данных), и, вероятно, его необходимо будет адаптировать, чтобы соответствовать ограничениям базы данных (например, может быть только быть выполнимым для нескольких сотен записей одновременно). Это следует рассматривать только после правильного использования соединения/транзакции, как описано выше.

Я не удивлюсь, если мы уже создали библиотеки/модули для массовой вставки... и я не использую MS Access, поэтому я могу только надеяться, что приведенные выше предложения были полезны :-)

Удачного кодирования.

person Community    schedule 22.12.2011
comment
Спасибо, pst, время доступа намного короче после того, как я переместил открытие/закрытие из цикла. К сожалению, MS Access поддерживает только одну команду SQL за раз.... - person Raymond; 30.12.2011
comment
@Raymond :( Я нашел это как вставить несколько строк, что согласуется. Убедитесь, что, как и в этом другом сообщении, вы используете одну транзакцию (или несколько пакетных транзакций), чтобы избежать накладных расходов на автоматическую фиксацию после каждой INSERT. (Если вы достигают только около 60 строк в секунду, я подозреваю, что транзакции ограничивают пропускную способность.) - person ; 30.12.2011

Не делайте ОДНУ вставку на команду. Измените свой код на что-то вроде этого:

string strSQLCommand;
for (int i = 0; i < populationSize; i++){
strSQLCommand += "INSERT INTO [" + pTableName + "] (" + columnsName + ") VALUES (" + columnsValue[i] + ");";`
}
outputDBConn->runSQLEdit(strSQLCommand );

Я не уверен, каков максимальный размер буфера команды, поэтому сделайте несколько проверок, а затем получите наилучшее значение, чтобы сделать несколько «разрывов» при каждой вставке X.

person João Augusto    schedule 22.12.2011
comment
Спасибо, но мне кажется, что MS Access не поддерживает более одной команды SQL за раз, поэтому каждый раз может выполнять только одну вставку..... - person Raymond; 30.12.2011