diff --git a/src/core/classes/sqlitedb.ts b/src/core/classes/sqlitedb.ts
index 0d5bce2df..649e81cc9 100644
--- a/src/core/classes/sqlitedb.ts
+++ b/src/core/classes/sqlitedb.ts
@@ -1169,6 +1169,8 @@ export class SQLiteDB {
      * @returns Spy methods.
      */
     protected getDatabaseSpies(db: SQLiteObject): Partial<SQLiteObject> {
+        const dbName = this.name;
+
         return {
             async executeSql(statement, params) {
                 const start = performance.now();
@@ -1180,6 +1182,7 @@ export class SQLiteDB {
                         params,
                         sql: statement,
                         duration:  performance.now() - start,
+                        dbName,
                     });
 
                     return result;
@@ -1189,6 +1192,7 @@ export class SQLiteDB {
                         error,
                         sql: statement,
                         duration:  performance.now() - start,
+                        dbName,
                     });
 
                     throw error;
@@ -1206,6 +1210,7 @@ export class SQLiteDB {
                     CoreDB.logQuery({
                         sql,
                         duration: performance.now() - start,
+                        dbName,
                     });
 
                     return result;
@@ -1214,6 +1219,7 @@ export class SQLiteDB {
                         sql,
                         error,
                         duration: performance.now() - start,
+                        dbName,
                     });
 
                     throw error;
diff --git a/src/core/features/emulator/classes/sqlitedb.ts b/src/core/features/emulator/classes/sqlitedb.ts
index 8b7f5c682..a761c6bd2 100644
--- a/src/core/features/emulator/classes/sqlitedb.ts
+++ b/src/core/features/emulator/classes/sqlitedb.ts
@@ -171,6 +171,8 @@ export class SQLiteDBMock extends SQLiteDB {
      * @inheritdoc
      */
     protected getDatabaseSpies(db: SQLiteObject): Partial<SQLiteObject> {
+        const dbName = this.name;
+
         return {
             transaction: (callback) => db.transaction((transaction) => {
                 const transactionSpy: DbTransaction = {
@@ -185,6 +187,7 @@ export class SQLiteDBMock extends SQLiteDB {
                                     sql,
                                     params,
                                     duration: performance.now() - start,
+                                    dbName,
                                 });
 
                                 return success?.(...args);
@@ -195,6 +198,7 @@ export class SQLiteDBMock extends SQLiteDB {
                                     params,
                                     error: args[0],
                                     duration: performance.now() - start,
+                                    dbName,
                                 });
 
                                 return error?.(...args);
diff --git a/src/core/services/db.ts b/src/core/services/db.ts
index 841f57aef..1d46b2ed3 100644
--- a/src/core/services/db.ts
+++ b/src/core/services/db.ts
@@ -20,6 +20,16 @@ import { CoreBrowser } from '@singletons/browser';
 import { makeSingleton, SQLite, Platform } from '@singletons';
 import { CoreAppProvider } from './app';
 
+const tableNameRegex = new RegExp([
+    '^SELECT.*FROM ([^ ]+)',
+    '^INSERT.*INTO ([^ ]+)',
+    '^UPDATE ([^ ]+)',
+    '^DELETE FROM ([^ ]+)',
+    '^CREATE TABLE IF NOT EXISTS ([^ ]+)',
+    '^ALTER TABLE ([^ ]+)',
+    '^DROP TABLE IF EXISTS ([^ ]+)',
+].join('|'));
+
 /**
  * This service allows interacting with the local database to store and retrieve data.
  */
@@ -42,10 +52,11 @@ export class CoreDbProvider {
     /**
      * Print query history in console.
      *
-     * @param format Log format, with the following substitutions: :sql, :duration, and :result.
+     * @param format Log format, with the following substitutions: :dbname, :sql, :duration, and :result.
      */
-    printHistory(format: string = ':sql | Duration: :duration | Result: :result'): void {
-        const substituteParams = ({ sql, params, duration, error }: CoreDbQueryLog) => format
+    printHistory(format: string = ':dbname | :sql | Duration: :duration | Result: :result'): void {
+        const substituteParams = ({ sql, params, duration, error, dbName }: CoreDbQueryLog) => format
+            .replace(':dbname', dbName)
             .replace(':sql', Object
                 .values(params ?? [])
                 .reduce((sql: string, param: string) => sql.replace('?', param) as string, sql) as string)
@@ -56,6 +67,120 @@ export class CoreDbProvider {
         console.log(this.queryLogs.map(substituteParams).join('\n'));
     }
 
+    /**
+     * Get the table name from a SQL query.
+     *
+     * @param sql SQL query.
+     * @return Table name, undefined if not found.
+     */
+    protected getTableNameFromSql(sql: string): string | undefined {
+        const matches = sql.match(tableNameRegex);
+
+        return matches?.find((matchEntry, index) => index > 0 && !!matchEntry);
+    }
+
+    /**
+     * Check if a value matches a certain filter.
+     *
+     * @param value Value.
+     * @param filter Filter.
+     * @return Whether the value matches the filter.
+     */
+    protected valueMatchesFilter(value: string, filter?: RegExp | string): boolean {
+        if (typeof filter === 'string') {
+            return value === filter;
+        } else if (filter) {
+            return !!value.match(filter);
+        }
+
+        return true;
+    }
+
+    /**
+     * Build an object with the summary data for each db, table and statement.
+     *
+     * @param filters Filters to limit the data stored.
+     * @return Object with the summary data.
+     */
+    protected buildStatementsSummary(
+        filters: TablesSummaryFilters = {},
+    ): Record<string, Record<string, Record<string, CoreDbStatementSummary>>> {
+        const statementsSummary: Record<string, Record<string, Record<string, CoreDbStatementSummary>>> = {};
+
+        this.queryLogs.forEach(log => {
+            if (!this.valueMatchesFilter(log.dbName, filters.dbName)) {
+                return;
+            }
+
+            const statement = log.sql.substring(0, log.sql.indexOf(' '));
+            if (!statement) {
+                console.warn(`Statement not found from sql: ${log.sql}`); // eslint-disable-line no-console
+
+                return;
+            }
+
+            const tableName = this.getTableNameFromSql(log.sql);
+            if (!tableName) {
+                console.warn(`Table name not found from sql: ${log.sql}`); // eslint-disable-line no-console
+
+                return;
+            }
+
+            if (!this.valueMatchesFilter(tableName, filters.tableName)) {
+                return;
+            }
+
+            statementsSummary[log.dbName] = statementsSummary[log.dbName] ?? {};
+            statementsSummary[log.dbName][tableName] = statementsSummary[log.dbName][tableName] ?? {};
+            statementsSummary[log.dbName][tableName][statement] = statementsSummary[log.dbName][tableName][statement] ?? {
+                count: 0,
+                duration: 0,
+                errors: 0,
+            };
+
+            statementsSummary[log.dbName][tableName][statement].count++;
+            statementsSummary[log.dbName][tableName][statement].duration += log.duration;
+            if (log.error) {
+                statementsSummary[log.dbName][tableName][statement].errors++;
+            }
+        });
+
+        return statementsSummary;
+    }
+
+    /**
+     * Print summary of statements for several tables.
+     *
+     * @param filters Filters to limit the results printed.
+     * @param format Log format, with the following substitutions: :dbname, :table, :statement, :count, :duration and :errors.
+     */
+    printTablesSummary(
+        filters: TablesSummaryFilters = {},
+        format = ':dbname, :table, :statement, :count, :duration, :errors',
+    ): void {
+        const statementsSummary = this.buildStatementsSummary(filters);
+
+        const substituteParams = (dbName: string,  tableName: string, statementName: string) => format
+            .replace(':dbname', dbName)
+            .replace(':table', tableName)
+            .replace(':statement', statementName)
+            .replace(':count', String(statementsSummary[dbName][tableName][statementName].count))
+            .replace(':duration', statementsSummary[dbName][tableName][statementName].duration + 'ms')
+            .replace(':errors', String(statementsSummary[dbName][tableName][statementName].errors));
+
+        // eslint-disable-next-line no-console
+        console.log(
+            Object.keys(statementsSummary)
+                .sort()
+                .map(dbName => Object.keys(statementsSummary[dbName])
+                    .sort()
+                    .map(tableName => Object.keys(statementsSummary[dbName][tableName])
+                        .sort()
+                        .map(statementName => substituteParams(dbName, tableName, statementName))
+                        .join('\n')).join('\n')).join('\n'),
+        );
+    }
+
     /**
      * Log a query.
      *
@@ -65,6 +190,13 @@ export class CoreDbProvider {
         this.queryLogs.push(log);
     }
 
+    /**
+     * Clear stored logs.
+     */
+    clearLogs(): void {
+        this.queryLogs = [];
+    }
+
     /**
      * Get or create a database object.
      *
@@ -125,8 +257,26 @@ export const CoreDB = makeSingleton(CoreDbProvider);
  * Database query log entry.
  */
 export interface CoreDbQueryLog {
+    dbName: string;
     sql: string;
     duration: number;
     error?: Error;
     params?: unknown[];
 }
+
+/**
+ * Summary about a certain DB statement.
+ */
+type CoreDbStatementSummary = {
+    count: number;
+    duration: number;
+    errors: number;
+};
+
+/**
+ * Filters to print tables summary.
+ */
+type TablesSummaryFilters = {
+    dbName?: RegExp | string;
+    tableName?: RegExp | string;
+};