Ответ 1
Я не думаю, что установка двух баз данных и запуск INSERT INTO foo (SELECT * FROM bar)
- это самый быстрый способ сделать это. Если вы синхронизируете между карманным устройством и сервером (или другим устройством), может ли транспортный механизм быть узким местом? Или два файла базы данных уже находятся на одном и том же файловом сервере? Если файловая система на устройстве медленнее флэш-памяти, может ли это быть узким местом?
Можете ли вы скомпилировать/запустить исходный код SQLite C на вашем устройстве? (Я думаю, что объединение RAW sqlite3 должно компилироваться для WinCE/Mobile). Если да, и вы согласны:
- Чтобы написать код C (используя API-интерфейс SQLite C)
- Повысить риск потери данных, отключив ведение журнала диска.
Должно быть возможно написать небольшой автономный исполняемый файл, чтобы очень быстро копировать/синхронизировать записи 100K между двумя базами данных.
Я опубликовал некоторые из того, что я узнал об оптимизации вложений SQLite здесь: Улучшить производительность SQLite в SQL Server?
Изменить: Пробовал это с помощью реального кода...
Я не знаю всех шагов, связанных с созданием исполняемого файла 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 секунды. Я точно не знаю, какую производительность вы увидите на мобильном устройстве с флеш-памятью (но мне любопытно).