Skip to content

Commit d58bfc2

Browse files
perf: speed up query for filling missing columns in refill metatable (#18)
The new query does 1 encode per source row and one indexed NOT-EXISTS probe. The old plan does many decodes per candidate and can’t use an index to rule out matches quickly—so it burns CPU and I/O. * Increased performance in cloudsync_refill_metatable * chore: remove old code * chore: bump version --------- Co-authored-by: Marco Bambini <[email protected]>
1 parent 73bc5a7 commit d58bfc2

File tree

3 files changed

+9
-13
lines changed

3 files changed

+9
-13
lines changed

src/cloudsync.c

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1711,25 +1711,22 @@ int cloudsync_refill_metatable (sqlite3 *db, cloudsync_context *data, const char
17111711
char *pkdecode = dbutils_text_select(db, sql);
17121712
char *pkdecodeval = (pkdecode) ? pkdecode : "cloudsync_pk_decode(pk, 1) AS rowid";
17131713
cloudsync_memory_free(sql);
1714-
1715-
sql = cloudsync_memory_mprintf("SELECT group_concat('\"' || format('%%w', name) || '\"' || ' = cloudsync_pk_decode(pk, ' || pk || ')', ' AND ') FROM pragma_table_info('%q') WHERE pk>0 ORDER BY pk;", table_name);
1716-
char *pkonclause = dbutils_text_select(db, sql);
1717-
char *pkonclauseval = (pkonclause) ? pkonclause : "rowid = cloudsync_pk_decode(pk, 1) AS rowid";
1718-
cloudsync_memory_free(sql);
1719-
1714+
17201715
sql = cloudsync_memory_mprintf("SELECT cloudsync_insert('%q', %s) FROM (SELECT %s FROM \"%w\" EXCEPT SELECT %s FROM \"%w_cloudsync\");", table_name, pkvalues_identifiers, pkvalues_identifiers, table_name, pkdecodeval, table_name);
17211716
int rc = sqlite3_exec(db, sql, NULL, NULL, NULL);
17221717
cloudsync_memory_free(sql);
17231718
if (rc != SQLITE_OK) goto finalize;
1724-
1719+
17251720
// fill missing colums
17261721
// for each non-pk column:
1722+
// The new query does 1 encode per source row and one indexed NOT-EXISTS probe.
1723+
// The old plan does many decodes per candidate and can’t use an index to rule out matches quickly—so it burns CPU and I/O.
17271724

1728-
sql = cloudsync_memory_mprintf("SELECT cloudsync_pk_encode(%s) FROM \"%w\" LEFT JOIN \"%w_cloudsync\" ON %s AND \"%w_cloudsync\".col_name = ? WHERE \"%w_cloudsync\".db_version IS NULL", pkvalues_identifiers, table_name, table_name, pkonclauseval, table_name, table_name);
1729-
rc = sqlite3_prepare(db, sql, -1, &vm, NULL);
1725+
sql = cloudsync_memory_mprintf("WITH _cstemp1 AS (SELECT cloudsync_pk_encode(%s) AS pk FROM \"%w\") SELECT _cstemp1.pk FROM _cstemp1 WHERE NOT EXISTS (SELECT 1 FROM \"%w_cloudsync\" _cstemp2 WHERE _cstemp2.pk = _cstemp1.pk AND _cstemp2.col_name = ?);", pkvalues_identifiers, table_name, table_name);
1726+
rc = sqlite3_prepare_v3(db, sql, -1, SQLITE_PREPARE_PERSISTENT, &vm, NULL);
17301727
cloudsync_memory_free(sql);
17311728
if (rc != SQLITE_OK) goto finalize;
1732-
1729+
17331730
for (int i=0; i<table->ncols; ++i) {
17341731
char *col_name = table->col_name[i];
17351732

@@ -1758,7 +1755,6 @@ int cloudsync_refill_metatable (sqlite3 *db, cloudsync_context *data, const char
17581755
if (rc != SQLITE_OK) DEBUG_ALWAYS("cloudsync_refill_metatable error: %s", sqlite3_errmsg(db));
17591756
if (pkclause_identifiers) cloudsync_memory_free(pkclause_identifiers);
17601757
if (pkdecode) cloudsync_memory_free(pkdecode);
1761-
if (pkonclause) cloudsync_memory_free(pkonclause);
17621758
if (vm) sqlite3_finalize(vm);
17631759
return rc;
17641760
}

src/cloudsync.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
extern "C" {
2121
#endif
2222

23-
#define CLOUDSYNC_VERSION "0.8.41"
23+
#define CLOUDSYNC_VERSION "0.8.51"
2424

2525
int sqlite3_cloudsync_init (sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi);
2626

test/unit.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5930,7 +5930,7 @@ int main(int argc, const char * argv[]) {
59305930
cloudsync_set_payload_apply_callback(db, unittest_payload_apply_rls_callback);
59315931

59325932
printf("Testing CloudSync version %s\n", CLOUDSYNC_VERSION);
5933-
printf("===============================\n");
5933+
printf("=================================\n");
59345934

59355935
result += test_report("PK Test:", do_test_pk(db, 10000, print_result));
59365936
result += test_report("UUID Test:", do_test_uuid(db, 1000, print_result));

0 commit comments

Comments
 (0)