面试题答案
一键面试数据库架构方面
- 读写分离:
- 使用主从复制,将读操作(商品展示等)分流到从库,主库专注于写操作(订单处理等)。例如,通过MySQL自带的复制功能,配置主库和多个从库,应用程序根据操作类型(读或写)来选择连接到主库或从库。
- 分库分表:
- 垂直分库:按业务模块将数据库拆分,如将商品数据和订单数据分别存放在不同的数据库中。例如,建立商品数据库存储商品相关的表,订单数据库存储订单相关的表,这样减少单个数据库的压力。
- 水平分表:对于数据量巨大的表,如订单表,按一定规则(如按时间、订单ID取模等)进行水平拆分。比如按月份将订单表拆分成不同的表,每个月的订单数据存放在对应的表中,减轻单表压力。
- 引入缓存:
- 在应用层和数据库层之间引入缓存,如Redis。对于频繁查询且不经常变化的数据,如商品的基本信息,先从缓存中获取,若缓存没有再查询数据库,并将查询结果写入缓存。例如,使用Jedis等客户端库在Java应用中操作Redis缓存。
查询优化方面
- 索引优化:
- 分析查询语句,为经常出现在
WHERE
、JOIN
、ORDER BY
等子句中的列创建合适的索引。例如,在订单表的user_id
列上创建索引,当查询某个用户的订单时可提高查询效率。但要注意避免创建过多索引,因为索引也会占用空间和影响写操作性能。
- 分析查询语句,为经常出现在
- 查询语句优化:
- 避免使用子查询,尽量使用连接(JOIN)来代替。例如,将
SELECT * FROM table1 WHERE column1 IN (SELECT column2 FROM table2)
改写为SELECT table1.* FROM table1 JOIN table2 ON table1.column1 = table2.column2
。 - 减少全表扫描,确保查询条件能利用索引。例如,查询语句
SELECT * FROM products WHERE product_name LIKE '%keyword%'
会导致全表扫描,可改写为SELECT * FROM products WHERE product_name LIKE 'keyword%'
,这样在product_name
列有索引时能利用索引。 - 优化
JOIN
操作,确保连接条件正确且高效。例如,对于INNER JOIN
,确保连接列上有索引,避免笛卡尔积的产生。
- 避免使用子查询,尽量使用连接(JOIN)来代替。例如,将
配置参数调整方面
- 内存相关参数:
- innodb_buffer_pool_size:适当增大该参数,它用于缓存InnoDB表的数据和索引。例如,对于一台有32GB内存的服务器,可将该参数设置为20GB左右,让更多的数据和索引能在内存中被快速访问,减少磁盘I/O。
- sort_buffer_size:根据系统中排序操作的频率和规模调整该参数。如果排序操作频繁且数据量较大,适当增大该参数,它用于在排序操作时分配的缓冲区大小。但要注意不能设置过大,否则会消耗过多内存。
- 磁盘I/O相关参数:
- innodb_flush_log_at_trx_commit:该参数控制InnoDB日志刷盘的频率。取值0表示每秒将日志缓冲区内容写入日志文件并刷盘;取值1(默认)表示每次事务提交时都将日志缓冲区内容写入日志文件并刷盘;取值2表示每次事务提交时将日志缓冲区内容写入日志文件,但每秒刷盘一次。在高并发写场景下,可根据数据安全性要求适当调整为2,减少磁盘I/O压力。
- innodb_io_capacity:设置InnoDB存储引擎的I/O能力,根据磁盘的实际性能进行调整。例如,对于SSD磁盘,可设置较高的值(如2000 - 3000),让InnoDB能更充分利用磁盘的I/O性能。