面试题答案
一键面试合适索引减少锁持有时间的原理
- 快速定位数据:合适的索引能让MySQL在查询数据时,通过索引快速定位到目标数据行,而无需全表扫描。这大大减少了扫描的数据量,从而减少了锁的持有时间。例如,在一个包含百万条记录的用户表
users
中,若要查询user_id = 123
的用户信息,如果没有索引,需要遍历全表;若在user_id
列上创建了索引,可直接定位到该记录,减少锁持有时间。 - 降低锁粒度:通过合适的索引,MySQL可以更精确地锁定所需的数据,从而降低锁粒度。比如在InnoDB存储引擎中,行锁依赖于索引,如果索引合适,就可以使用行锁而非表锁,减少对其他数据的影响,缩短锁持有时间。
设计索引时避免长时间持有锁的考虑因素
- 索引类型选择
- 主键索引:每个表应该有一个主键索引,它具有唯一性且不能为空。主键索引能快速定位记录,减少锁等待。例如在订单表
orders
中,以order_id
作为主键索引,在对特定订单操作时能迅速定位,减少锁时间。 - 普通索引:适用于经常用于查询条件的列。例如在用户表
users
中,经常根据email
查询用户,在email
列创建普通索引,可加快查询,减少锁持有。 - 唯一索引:用于确保列值的唯一性,同时也能加速查询。如在用户表
users
中,phone_number
列可创建唯一索引,保证手机号唯一且加快查询该手机号用户的速度。
- 主键索引:每个表应该有一个主键索引,它具有唯一性且不能为空。主键索引能快速定位记录,减少锁等待。例如在订单表
- 覆盖索引的应用:覆盖索引指的是一个查询语句的执行只需要从索引中就能够获取所有需要的数据,而不必回表查询。这样避免了二次查找数据行,从而减少锁持有时间。例如查询语句
SELECT user_name FROM users WHERE user_id = 123
,如果在user_id
和user_name
列上创建联合索引,这个查询就可以利用覆盖索引,无需回表,减少锁持有。 - 前缀索引:当列值较长时,可使用前缀索引。例如在
address
列存储用户详细地址,若直接创建索引可能占用过多空间且效率不高,可创建前缀索引CREATE INDEX idx_address ON users (address(10));
,只对前10个字符创建索引,在一定程度上减少索引空间和查询时间,进而减少锁持有时间。 - 避免索引冗余:冗余索引是指多个索引之间存在重复或者包含关系。如已经有索引
CREATE INDEX idx_user_name ON users (user_name);
,又创建CREATE INDEX idx_user_name_email ON users (user_name, email);
,其中idx_user_name
就是冗余索引。冗余索引会增加索引维护成本,导致锁操作更复杂,所以要避免。