面试题答案
一键面试索引结构选择
- B - Tree索引:适用于范围查询、排序等操作。在高并发写入场景下,B - Tree索引的插入操作可能导致页分裂,影响性能。可以考虑适当增大页大小,减少页分裂频率。例如,在MySQL中通过修改
innodb_page_size
参数(需重启数据库且影响数据文件格式),来调整B - Tree页的大小。 - 哈希索引:哈希索引在等值查询时性能极高,并且插入操作相对简单,不会像B - Tree那样频繁产生页分裂。但哈希索引不支持范围查询和排序。如果应用场景中主要是基于唯一键的插入操作,哈希索引可能是个不错的选择。在MySQL中,Memory存储引擎默认使用哈希索引,InnoDB引擎也支持自适应哈希索引(AHI),AHI由InnoDB自动管理,当某些索引值被频繁访问时,InnoDB会自动在内存中基于B - Tree索引构建哈希索引以加速查询。
索引创建原则
- 尽量减少索引数量:过多的索引会增加写入时的维护成本。每插入一条数据,数据库都需要更新相关的索引。例如,只在经常用于查询条件、排序和连接的字段上创建索引。对于很少使用的查询条件字段,不要创建索引。
- 覆盖索引:如果查询的字段都包含在索引中,那么查询时直接通过索引就能获取数据,无需回表操作,这能减少I/O次数。例如,
SELECT column1, column2 FROM table WHERE column1 = 'value'
,若在(column1, column2)
上创建联合索引,就形成了覆盖索引。 - 前缀索引:对于较长的字符串字段,可以使用前缀索引。例如,对于一个很长的
varchar
类型的address
字段,在该字段上创建索引时可以指定前缀长度,如CREATE INDEX idx_address ON table(address(10))
,这样可以减少索引占用的空间,提升写入性能。不过使用前缀索引要注意前缀长度的选择,既要保证足够的区分度,又不能过长导致失去前缀索引的意义。
数据库参数配置
- innodb_flush_log_at_trx_commit:该参数控制InnoDB存储引擎将日志缓冲区中的日志写入磁盘并刷新到磁盘的频率。有三个取值:
0
:每秒将日志缓冲区的日志写入日志文件并刷新到磁盘。这种设置性能最高,但如果数据库崩溃,可能会丢失1秒内的事务数据。1
(默认值):每次事务提交时,将日志缓冲区的日志写入日志文件并刷新到磁盘。这种设置保证了数据的一致性,但在高并发写入时,频繁的磁盘I/O可能成为性能瓶颈。2
:每次事务提交时,将日志缓冲区的日志写入日志文件,但每秒才刷新到磁盘。这种设置在性能和数据安全性之间做了一个折中,若数据库崩溃,可能会丢失1秒内提交的事务数据,但不会丢失未提交的事务数据。在高并发写入场景下,可以根据应用对数据一致性和性能的要求,适当调整为2
。
- innodb_buffer_pool_size:InnoDB缓冲池是InnoDB存储引擎用来缓存数据和索引的内存区域。增大该参数值,可以让更多的数据和索引缓存在内存中,减少磁盘I/O。在高并发写入场景下,足够大的缓冲池可以容纳更多的新写入数据和索引,提升系统性能。例如,对于内存充足的服务器,可以将其设置为物理内存的70% - 80%。但也要注意,设置过大可能导致操作系统内存不足。
- innodb_thread_concurrency:该参数限制了InnoDB存储引擎可以同时进入内核的线程数量。在高并发写入场景下,如果线程数过多,可能会导致CPU资源竞争激烈,性能下降。通过合理设置该参数,可以避免过度的线程竞争。例如,可以根据服务器的CPU核心数来设置,一般设置为CPU核心数的2倍左右。但具体值还需要通过性能测试来确定。