面试题答案
一键面试预处理语句的缓存
- 原理:在SQLite中,预处理语句缓存可以避免每次执行查询时都进行编译和优化的开销。当相同的SQL语句结构(仅参数不同)被重复执行时,缓存的预处理语句可以直接被复用。
- 实现:不同编程语言操作SQLite时实现方式略有不同。例如在Python中使用
sqlite3
模块:
import sqlite3
# 连接数据库
conn = sqlite3.connect('example.db')
cursor = conn.cursor()
# 预编译SQL语句
sql = "SELECT * FROM large_table WHERE column1 =? AND column2 =?"
# 缓存预处理语句,多次执行不同参数的查询
parameters_list = [(1, 'value1'), (2, 'value2')]
for parameters in parameters_list:
cursor.execute(sql, parameters)
results = cursor.fetchall()
for row in results:
print(row)
conn.close()
在上述代码中,execute
方法会复用预编译的sql
语句,只是每次传入不同的参数。
绑定参数的方式
- 正确使用占位符:
- 原理:使用占位符(如
?
在Python的sqlite3
模块中)而不是直接拼接SQL语句。直接拼接SQL语句不仅容易导致SQL注入问题,而且SQLite无法有效地缓存和优化拼接后的动态SQL。 - 示例:错误方式
- 原理:使用占位符(如
import sqlite3
conn = sqlite3.connect('example.db')
cursor = conn.cursor()
param1 = 1
param2 = 'value1'
# 错误的拼接方式,不推荐
sql_bad = "SELECT * FROM large_table WHERE column1 = " + str(param1) + " AND column2 = '" + param2 + "'"
cursor.execute(sql_bad)
results = cursor.fetchall()
for row in results:
print(row)
conn.close()
- **正确方式**:
import sqlite3
conn = sqlite3.connect('example.db')
cursor = conn.cursor()
param1 = 1
param2 = 'value1'
sql_good = "SELECT * FROM large_table WHERE column1 =? AND column2 =?"
cursor.execute(sql_good, (param1, param2))
results = cursor.fetchall()
for row in results:
print(row)
conn.close()
- 批量绑定参数:
- 原理:当需要执行多次参数化查询时,批量执行可以减少与数据库的交互次数,从而提高性能。
- 示例:在Python中:
import sqlite3
conn = sqlite3.connect('example.db')
cursor = conn.cursor()
sql = "INSERT INTO some_table (column1, column2) VALUES (?,?)"
data = [(1, 'a'), (2, 'b'), (3, 'c')]
cursor.executemany(sql, data)
conn.commit()
conn.close()
在上述代码中,executemany
方法一次性将多个参数集传递给SQLite执行,减少了多次调用execute
的开销。
其他优化策略
- 索引优化:
- 原理:为查询涉及的列创建合适的索引可以大大加快查询速度。对于参数化查询中
WHERE
子句涉及的列,如果没有索引,SQLite可能需要全表扫描。 - 示例:
- 原理:为查询涉及的列创建合适的索引可以大大加快查询速度。对于参数化查询中
CREATE INDEX idx_column1_column2 ON large_table (column1, column2);
上述SQL语句为large_table
表的column1
和column2
列创建了联合索引,在执行SELECT * FROM large_table WHERE column1 =? AND column2 =?
这类查询时可以利用该索引提升性能。
2. 查询语句优化:
- 原理:确保查询语句本身的逻辑是最优的。例如,避免使用SELECT *
,只选择需要的列,减少数据传输和处理的开销。
- 示例:
-- 不好的方式,返回所有列
SELECT * FROM large_table WHERE column1 =? AND column2 =?;
-- 好的方式,只返回需要的列
SELECT column3, column4 FROM large_table WHERE column1 =? AND column2 =?;