Я не думаю, что присоединение двух баз данных и запуск INSERT INTO foo (SELECT * FROM bar) - самый быстрый способ сделать это. Если вы выполняете синхронизацию между портативным устройством и сервером (или другим устройством), может ли транспортный механизм быть узким местом? Или два файла базы данных уже находятся в одной файловой системе? Если файловая система на устройстве медленнее flash-памяти, может ли это быть узким местом?
Можете ли вы скомпилировать / запустить необработанный код SQLite C на своем устройстве? (Я думаю, что объединение RAW sqlite3 должно компилироваться для WinCE / Mobile) Если это так, и вы готовы:
- Чтобы написать код C (используя SQLite C API)
- Увеличьте риск потери данных, отключив ведение журнала диска
Должна существовать возможность написать небольшой автономный исполняемый файл для очень быстрого копирования / синхронизации 100К записей между двумя базами данных.
Я разместил здесь кое-что из того, что узнал об оптимизации вставок SQLite: Улучшить ВСТАВИТЬ производительность SQLite в секунду?
Изменить: Пробовал это с реальным кодом ...
Я не знаю всех этапов создания исполняемого файла Windows Mobile, но объединение SQLite3 должно компилироваться прямо из коробки с помощью Visual Studio. Вот пример main.c программы, которая открывает две базы данных SQLite (обе должны иметь одинаковую схему - см. Оператор #define TABLE) и выполняет оператор SELECT, а затем связывает полученные строки с оператором INSERT:
/*************************************************************
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include "sqlite3.h"
#define SOURCEDB "C:\\source.sqlite"
#define DESTDB "c:\\dest.sqlite"
#define TABLE "CREATE TABLE IF NOT EXISTS TTC (id INTEGER PRIMARY KEY, Route_ID TEXT, Branch_Code TEXT, Version INTEGER, Stop INTEGER, Vehicle_Index INTEGER, Day Integer, Time TEXT)"
#define BUFFER_SIZE 256
int main(int argc, char **argv) {
sqlite3 * sourceDB;
sqlite3 * destDB;
sqlite3_stmt * insertStmt;
sqlite3_stmt * selectStmt;
char * insertTail = 0;
char * selectTail = 0;
int n = 0;
int result = 0;
char * sErrMsg = 0;
clock_t cStartClock;
char sInsertSQL [BUFFER_SIZE] = "\0";
char sSelectSQL [BUFFER_SIZE] = "\0";
/* Open the Source and Destination databases */
sqlite3_open(SOURCEDB, &sourceDB);
sqlite3_open(DESTDB, &destDB);
/* Risky - but improves performance */
sqlite3_exec(destDB, "PRAGMA synchronous = OFF", NULL, NULL, &sErrMsg);
sqlite3_exec(destDB, "PRAGMA journal_mode = MEMORY", NULL, NULL, &sErrMsg);
cStartClock = clock(); /* Keep track of how long this took*/
/* Prepared statements are much faster */
/* Compile the Insert statement */
sprintf(sInsertSQL, "INSERT INTO TTC VALUES (NULL, @RT, @BR, @VR, @ST, @VI, @DT, @TM)");
sqlite3_prepare_v2(destDB, sInsertSQL, BUFFER_SIZE, &insertStmt, &insertTail);
/* Compile the Select statement */
sprintf(sSelectSQL, "SELECT * FROM TTC LIMIT 100000");
sqlite3_prepare_v2(sourceDB, sSelectSQL, BUFFER_SIZE, &selectStmt, &selectTail);
/* Transaction on the destination database */
sqlite3_exec(destDB, "BEGIN TRANSACTION", NULL, NULL, &sErrMsg);
/* Execute the Select Statement. Step through the returned rows and bind
each value to the prepared insert statement. Obviously this is much simpler
if the columns in the select statement are in the same order as the columns
in the insert statement */
result = sqlite3_step(selectStmt);
while (result == SQLITE_ROW)
{
sqlite3_bind_text(insertStmt, 1, sqlite3_column_text(selectStmt, 1), -1, SQLITE_TRANSIENT); /* Get Route */
sqlite3_bind_text(insertStmt, 2, sqlite3_column_text(selectStmt, 2), -1, SQLITE_TRANSIENT); /* Get Branch */
sqlite3_bind_text(insertStmt, 3, sqlite3_column_text(selectStmt, 3), -1, SQLITE_TRANSIENT); /* Get Version */
sqlite3_bind_text(insertStmt, 4, sqlite3_column_text(selectStmt, 4), -1, SQLITE_TRANSIENT); /* Get Stop Number */
sqlite3_bind_text(insertStmt, 5, sqlite3_column_text(selectStmt, 5), -1, SQLITE_TRANSIENT); /* Get Vehicle */
sqlite3_bind_text(insertStmt, 6, sqlite3_column_text(selectStmt, 6), -1, SQLITE_TRANSIENT); /* Get Date */
sqlite3_bind_text(insertStmt, 7, sqlite3_column_text(selectStmt, 7), -1, SQLITE_TRANSIENT); /* Get Time */
sqlite3_step(insertStmt); /* Execute the SQL Insert Statement (Destination Database)*/
sqlite3_clear_bindings(insertStmt); /* Clear bindings */
sqlite3_reset(insertStmt); /* Reset VDBE */
n++;
/* Fetch next from from source database */
result = sqlite3_step(selectStmt);
}
sqlite3_exec(destDB, "END TRANSACTION", NULL, NULL, &sErrMsg);
printf("Transfered %d records in %4.2f seconds\n", n, (clock() - cStartClock) / (double)CLOCKS_PER_SEC);
sqlite3_finalize(selectStmt);
sqlite3_finalize(insertStmt);
/* Close both databases */
sqlite3_close(destDB);
sqlite3_close(sourceDB);
return 0;
}
На моем настольном компьютере с Windows этот код копирует 100 тыс. записей из source.sqlite в dest.sqlite за 1,20 секунды. Я не знаю точно, какую производительность вы увидите на мобильном устройстве с флэш-памятью (но я любопытный).
person
Mike Willekes
schedule
05.02.2010