面试题答案
一键面试可能影响性能的因素
- 频繁的数据库I/O操作:每次查询都直接与SQLite交互,I/O开销大。
- 复杂查询语句:复杂的查询逻辑,如多表连接、嵌套子查询等,会增加数据库的处理负担。
- 未正确使用索引:没有为经常查询的字段创建索引,导致全表扫描。
- 数据量过大:表中数据过多,即使有索引,查询也会变慢。
优化方案及Flutter代码实现方式
- 缓存数据
- 原理:将经常查询的数据缓存到内存中,减少对数据库的直接查询次数。
- 实现方式:在Flutter中,可以使用
MemoryCache
类来实现简单的内存缓存。例如:
class MemoryCache {
static final MemoryCache _instance = MemoryCache._();
factory MemoryCache() => _instance;
MemoryCache._();
final Map<String, dynamic> _cache = {};
dynamic get(String key) => _cache[key];
void put(String key, dynamic value) => _cache[key] = value;
}
在查询数据库前,先检查缓存:
final cache = MemoryCache();
dynamic data = cache.get('query_key');
if (data == null) {
// 执行数据库查询
data = await database.rawQuery('SELECT * FROM your_table');
cache.put('query_key', data);
}
- 优化查询语句
- 原理:简化复杂查询,尽量避免不必要的子查询和多表连接,能拆分的查询尽量拆分。
- 实现方式:假设原本有一个复杂的多表连接查询:
// 原始复杂查询
List<Map<String, dynamic>> result = await database.rawQuery('''
SELECT a.column1, b.column2
FROM table1 a
JOIN table2 b ON a.id = b.table1_id
WHERE a.some_column =? AND b.another_column =?
''', ['value1', 'value2']);
可以尝试拆分成两个查询,先从table1
获取符合条件的id
,再根据id
查询table2
:
// 拆分查询
List<Map<String, dynamic>> result1 = await database.rawQuery('''
SELECT id
FROM table1
WHERE some_column =?
''', ['value1']);
List<int> ids = result1.map((e) => e['id'] as int).toList();
List<Map<String, dynamic>> result2 = await database.rawQuery('''
SELECT column2
FROM table2
WHERE table1_id IN (${ids.map((id) => '?').join(', ')}) AND another_column =?
''', [...ids, 'value2']);
- 使用索引
- 原理:为经常用于查询条件的字段创建索引,加快查询速度。
- 实现方式:在创建表时或者之后添加索引。例如,创建表时添加索引:
await database.execute('''
CREATE TABLE your_table (
id INTEGER PRIMARY KEY,
some_column TEXT,
another_column TEXT
);
CREATE INDEX idx_some_column ON your_table(some_column);
''');
查询时就可以利用索引:
List<Map<String, dynamic>> result = await database.rawQuery('''
SELECT * FROM your_table WHERE some_column =?
''', ['value']);
- 分页查询
- 原理:当数据量过大时,通过分页减少单次查询的数据量。
- 实现方式:使用
LIMIT
和OFFSET
关键字。例如:
int pageSize = 10;
int pageNumber = 0;
List<Map<String, dynamic>> result = await database.rawQuery('''
SELECT * FROM your_table
LIMIT? OFFSET?
''', [pageSize, pageNumber * pageSize]);