SQL Server / MySQL / Access - ускорение вставки многих строк неэффективным способом - PullRequest
5 голосов
/ 07 января 2009

SETUP

Мне нужно вставить пару миллионов строк в SQL Server 2000/2005, MySQL или Access. К сожалению, у меня нет простого способа использовать массовую вставку или BCP или любой другой способ, которым нормальный человек мог бы пойти по этому поводу. Вставки будут происходить в одну конкретную базу данных, но этот код должен быть независимым от БД - поэтому я не могу делать массовое копирование, или ВЫБРАТЬ В, или BCP. Однако я могу выполнять определенные запросы до и после вставок, в зависимости от того, в какую базу данных я импортирую.

например.

If IsSqlServer() Then
    DisableTransactionLogging();
ElseIf IsMySQL() Then
    DisableMySQLIndices();
End If

... do inserts ...

If IsSqlServer() Then
    EnableTransactionLogging();
ElseIf IsMySQL() Then
    EnableMySQLIndices();
End If

ВОПРОС

Есть ли какие-нибудь интересные вещи, которые я могу сделать с SQL Server, которые могли бы ускорить эти вставки?

Например, есть ли команда, которую я мог бы выполнить, чтобы сказать SQL Server: «Эй, не беспокойтесь о записи этих транзакций в журнал транзакций».

Или, может быть, я мог бы сказать: «Эй, у меня есть миллион строк, поэтому не обновляйте свой индекс, пока я полностью не закончу».

ALTER INDEX [IX_TableIndex] ON Table DISABLE
     ... inserts
ALTER INDEX [IX_TableIndex] ON Table REBUILD

(Примечание: отключение индекса выше работает только в 2005 году, но не в 2000 году. Бонусные баллы, если вы знаете способ сделать это в 2000 году).

А как насчет MySQL и Access?

Ответы [ 11 ]

4 голосов
/ 08 января 2009

Самая большая вещь, которая снижает производительность, это тот факт, что (похоже, что) вы выполняете миллион различных INSERT для БД. Каждая ВСТАВКА рассматривается как отдельная операция. Если вы можете сделать это как одну операцию, то вы почти наверняка значительно улучшите производительность.

И MySQL, и SQL Server поддерживают "выборки" константных выражений без имени таблицы, поэтому это должно работать как один оператор:

INSERT INTO MyTable(ID, name)
SELECT 1, 'Fred'
UNION ALL SELECT 2, 'Wilma'
UNION ALL SELECT 3, 'Barney'
UNION ALL SELECT 4, 'Betty'

Мне неясно, поддерживает ли Access это, не имея Access. ОДНАКО, насколько я могу судить, Access поддерживает константы в SELECT, и вы можете привести приведенное выше в ANSI SQL-92 (который должен поддерживаться всеми 3 механизмами; он примерно так же близок к «независимости от БД», как вы » получу), просто добавив

FROM OneRowTable

до конца каждого отдельного SELECT, где 'OneRowTable' - это таблица с одной строкой фиктивных данных.

Это должно позволить вам вставить миллион строк данных гораздо меньше, чем миллион операторов INSERT - и такие вещи, как перестановка индексов, будут выполняться один раз, а не миллион раз. После этого вам может понадобиться меньше оптимизаций.

2 голосов
/ 07 января 2009

это обычный процесс или одноразовое событие?

В прошлом я просто записывал текущие индексы, удалял их, вставлял строки, а затем просто добавлял индексы.

SQL Management Studio может записывать индексы из меню, вызываемого правой кнопкой мыши ...

1 голос
/ 07 января 2009

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

1 голос
/ 07 января 2009

Для SQL Server:

  1. Вы можете установить модель восстановления "Простой", чтобы журнал транзакций оставался небольшим. Не забудьте потом вернуться обратно.
  2. Отключение индексов на самом деле хорошая идея. Это будет работать на SQL 2005, а не на SQL Server 2000.

    изменить индекс [INDEX_NAME] в [TABLE_NAME] отключить

А для включения

alter index [INDEX_NAME] on [TABLE_NAME] rebuild

А затем просто вставьте строки одну за другой. Вы должны быть терпеливы, но, по крайней мере, это немного быстрее.

0 голосов
/ 02 февраля 2010

Стоит рассмотреть разбивку ваших вкладышей на более мелкие партии ; Одна транзакция с большим количеством запросов будет медленной.

0 голосов
/ 10 января 2009

Можете ли вы использовать DTS (2000) или SSIS (2005) для создания пакета, чтобы сделать это? DTS и SSIS могут одновременно извлекать данные из одного источника и отправлять их в разные потенциальные пункты назначения. Перейти на SSIS, если можете. Есть много хороших, быстрых технологий, а также функциональность для встраивания логики IsSQLServer, IsMySQL и т. Д.

0 голосов
/ 08 января 2009

SQL Server 2000/2005, MySQL и Access могут загружаться напрямую из текстового файла tab / cr, для этого у них просто разные команды. Если у вас есть инструкция case, чтобы определить, в какую базу данных вы импортируете, просто выясните их предпочтения при импорте текстового файла.

0 голосов
/ 08 января 2009

Рассматривали ли вы использовать шаблон Factory? Я предполагаю, что вы пишете код для этого, поэтому, используя шаблон фабрики, вы могли бы написать код фабрики, которая вернула конкретный класс типа «IDataInserter», который бы выполнял эту работу.

Это все равно позволит вам быть независимым от данных и получить самый быстрый метод для каждого типа базы данных.

0 голосов
/ 08 января 2009

Если это не то, что нужно ужасно быстро читать, вы можете сделать «Вставка с задержкой» в таблицу на MySQL. Это позволяет вашему коду продолжить работу, не дожидаясь фактической вставки. Это имеет некоторые ограничения, но если ваша главная задача - чтобы программа быстро заканчивалась, это может помочь. Имейте в виду, что есть хороший длинный список ситуаций, в которых это может действовать не так, как ожидалось. Проверьте документы .

Я не знаю, работает ли эта функция для Access или MS SQL.

0 голосов
/ 07 января 2009

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

Сама вещь с отключением индексов, это отключает для всех и может заставить базу данных работать медленнее, чем слаг.

Предлагаем запустить импорт партиями.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...