Вставка миллиона маленьких записей в Extensible Storage Engine (JetBlue) - быстро - PullRequest
4 голосов
/ 12 декабря 2010

Я надеюсь, что Лорион Бурчалл читает это: -)

Мне нужно как можно быстрее вставить миллион крошечных записей.

Сейчас я нахожусь в очень тесном цикле, где для каждой записи я

a) start a transaction  (JetBeginTransaction)
b) prepare an update (JetPrepareUpdate)
c) add the row (JetSetColumns)
d) commit the transaction (JetCommitTransaction)

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

Мне интересно, как получить лучшую производительность.

Что касается транзакций, я проводил некоторые эксперименты, и у меня возникали проблемы с возвращением ошибок, если я помещал слишком много данных в одну транзакцию. Я хотел бы лучше понять, что там происходит - есть ли у меня ошибка или размер транзакции ограничен, если ограничен, могу ли я увеличить ограничение? Я только исследую это, потому что предполагаю, что транзакция даст ESE возможность больше кэшировать в ОЗУ, минимизируя объемы сброса диска? - это всего лишь предположение?

Как вообще использовать несколько процессоров / много оперативной памяти / и хорошие диски? открыть базу данных дважды и перейти оттуда? Я не совсем уверен, что происходит в отношении безопасности потоков и транзакций. Если у меня есть два дескриптора для БД, каждый в транзакции, будет ли запись в один дескриптор доступна для второго сразу же, перед фиксацией, или мне нужно будет зафиксировать первый?

Любые советы приветствуются

    here are the constraints    

a) I've got a million records that need to be written into the DB as fast as possible
b) to fully generate the record for insertion there are two searches that need to occur within the same table (seeking keys)
c) This is a rebuild/regeneration of the DB - it either worked, or it didnt.  
   If it didnt there is no going back, a fresh rebuild/regeneration is
   needed.  I cannot restart mid process and without all the data none of 
   the data is valuable.  READ: having one big transaction is fine if it 
   improves perf.  I'd like ESE to cache, in ram, if that helps perf.

спасибо!

Ответы [ 2 ]

5 голосов
/ 14 декабря 2010

Для однопоточной производительности наиболее важная вещь - это модель транзакции.

Если вы попытались поместить больше данных в одну транзакцию, но она не удалась, вы, вероятно, получили JET_errOutOfVersionStore.Esent должен отслеживать информацию об отмене для всех операций, выполненных в транзакции (чтобы включить откат), и эта информация сохраняется в хранилище версий.Размер хранилища версий по умолчанию довольно мал.Вы можете увеличить его с помощью системного параметра JET_paramMaxVerPages.Значение 1024 (64 МБ хранилища версий) будет включать довольно большие транзакции.Я предлагаю делать 100-1000 вставок на транзакцию.

При вызове JetCommitTransaction Esent будет сбрасывать журнал на диск, генерируя синхронный ввод-вывод.Чтобы избежать этого, передайте JET_bitCommitLazyFlush в JetCommitTransaction.Ваши транзакции будут по-прежнему атомарными, но не долговечными в случае сбоя (все будет хорошо, если вы выйдете в обычном режиме).Похоже, что это должно быть найдено для вашего использования.

Если вы вставляете записи в порядке возрастания, то вам, возможно, удастся обойтись без однопоточного приложения.Если вы можете изменить свою реализацию, чтобы сделать последовательные вставки, вы должны - они намного быстрее.Для случайных вставок может быть полезно несколько потоков.Чтобы использовать несколько потоков, вам просто нужно создать новые сеансы (JetBeginSession) и открыть им базу данных (JetOpenDatabase).Esent использует изоляцию моментальных снимков (http://en.wikipedia.org/wiki/Snapshot_isolation), поэтому не может видеть изменения, сделанные другими сеансами, которые не были зафиксированы или зафиксированы после начала транзакции. Это отличается от фиксации чтения, когда вы можете видеть изменения после фиксации другого сеанса.нужно подумать о том, как разделить работу, чтобы справиться с этим.

1 голос
/ 25 февраля 2013

Убедитесь, что вы вставляете «по порядку». Что такое кластерный (первичный) ключ? Это искусственное авто-вкл? Если так, то вы вставляете по порядку. Сколько у вас вторичных индексов? В идеале у вас не должно быть ни одного, чтобы все вставки, например, только кластерная вставка будет в порядке индекса. Когда вы вставляете в порядке индекса, JetUpdate просто добавляет в конец индекса. Это намного быстрее, чем вставка в середину индекса. Надеюсь, это поможет, Ян.

...