Так як потужність клієнтських комп'ютерів зараз висока, то мільйони рядків в локальній БД вже
не є проблемою для обробки таких обсягів, але можуть створити вузьке місце при
інформаційному обміні.
Приватним прикладом є імпорт даних в локальну БД MS Access з віддаленого джерела. За умовами завдання необхідно максимально абстрагуватися від джерела даних. Ми заздалегідь не знаємо, яким способом користувач буде синхронізувати свою БД. Вибір MS Access в якості локальної БД також не є постулатом, незважаючи на популярність "движка" і простоту розгортання, можлива міграція в бік MS SQL Express або FireBird. Тому необхідно абстаргіроваться і від приймача.
Для MS Access найбільш очевидний варіант - використання ADO / ADO.Net, як ключовий технології доступу до даних в Windows. Менш очевидний ODBC. Ще менш "згадує" варіант - DAO, хоча він забезпечує дещо вищу швидкість при роботі з JET (MS
Access) і Excel.
adCmdTable (CommandType для Recordset-а)
Збереження записів проводилося в пакетному режимі з інтервалом в 10 тисяч записів.
Target. UpdateBatch # 40; adAffectAll # 41; ;
Результати (ви їх можете перевірити, запустивши тестовий приклад на своєму комп'ютері):
ADO
Time elapsed: 17,53 sec
Time elapsed per 1000 records: 0,04 sec
DAO
Time elapsed: 12,56 sec
Time elapsed per 1000 records: 0,03 sec
Здавалося б, якщо хочеться виграти ще кілька відсотків - беремо DAO. Але не поспішайте з висновками. Якщо крім швидкості у вас є інші критерії, то вибір стає не таким очевидним.
По-перше, швидкість ADO на практиці так само велика - десятки тисяч записів в секунду. Упевнений, в більшості випадків цього вистачить в рамках завдання.
По-третє, сам джерело може передавати інформацію з набагато меншою швидкістю, ніж та, з якою приймач готовий їх обробляти. Таке можливо, наприклад, при синхронізації через веб-сервіс в інтернет. Тобто, вузьким місцем, що вимагає оптимізації, буде не запис даних, а їх пересилання.
доповнення
У Delphi обгортка над ADO в вигляді TCustomADODataSet і нащадків (TADOQuery, TADOTable і т.п.) має неприємну особливість - вона уповільнює навігацію по записах і полях при відносно великій їх кількості. На щастя, це проявляється лише при великих розмірах DataSet - десятки тисяч записів - і статичному курсорі на клієнті.
В такому типовому циклі обробки відбувається істотне уповільнення, причому воно поступово наростає (за спостереженнями, логарифмічно). У нашому випадку швидкість обробки не перевищувала 1000 записів в секунду. Вихід із ситуації - використовувати доступ до ADO recordset безпосередньо.
Швидкість при цьому зростає на порядок до гортання десятків тисяч записів в секунду.
Перевірив Ваш метод імпорту даних - чудово працює. Але є одне Велике АЛЕ.
Як боротися з дублікатами?
Припустимо в таблиці вже є кілька записів. По одному з полів побудований унікальний індекс.
Тепер пробуємо заімпортіровать, скажімо, 10000 записів. І серед цих записів попадається одна,
яка призведе до появи дубліката індексу.
Як скіпнуть цей запис, щоб інші 9999 вставили?
Є 2 основні рішення:
- перевіряти ДО вставки
- перевіряти ПІСЛЯ вставки
Перевірку під час операції виключаємо, тому що вона погіршить швидкість пакетної вставки.
Перевірка до вставки - це, наприклад, запит до джерела даних, в якому ви виключаєте дублікати
Перевірка після вставки (сама вставка може виявитися більш швидкої): потрібно просто видалити тимчасово ключ (обмеження цілісності або унікальний індекс), а після вставки проаналізувати записи, виключити дублікати і відтворити ключ.