MST

星途 面试题库

面试题:MySQL索引与避免长时间持有锁的关系及优化策略

索引在MySQL性能优化中起着关键作用,同时也与锁的持有时间密切相关。请阐述合适的索引如何帮助减少锁的持有时间,以及在设计索引时,针对避免长时间持有锁需要考虑哪些因素,例如索引的类型选择、覆盖索引的应用等,并举例说明。
35.7万 热度难度
数据库MySQL

知识考点

AI 面试

面试题答案

一键面试

合适索引减少锁持有时间的原理

  1. 快速定位数据:合适的索引能让MySQL在查询数据时,通过索引快速定位到目标数据行,而无需全表扫描。这大大减少了扫描的数据量,从而减少了锁的持有时间。例如,在一个包含百万条记录的用户表users中,若要查询user_id = 123的用户信息,如果没有索引,需要遍历全表;若在user_id列上创建了索引,可直接定位到该记录,减少锁持有时间。
  2. 降低锁粒度:通过合适的索引,MySQL可以更精确地锁定所需的数据,从而降低锁粒度。比如在InnoDB存储引擎中,行锁依赖于索引,如果索引合适,就可以使用行锁而非表锁,减少对其他数据的影响,缩短锁持有时间。

设计索引时避免长时间持有锁的考虑因素

  1. 索引类型选择
    • 主键索引:每个表应该有一个主键索引,它具有唯一性且不能为空。主键索引能快速定位记录,减少锁等待。例如在订单表orders中,以order_id作为主键索引,在对特定订单操作时能迅速定位,减少锁时间。
    • 普通索引:适用于经常用于查询条件的列。例如在用户表users中,经常根据email查询用户,在email列创建普通索引,可加快查询,减少锁持有。
    • 唯一索引:用于确保列值的唯一性,同时也能加速查询。如在用户表users中,phone_number列可创建唯一索引,保证手机号唯一且加快查询该手机号用户的速度。
  2. 覆盖索引的应用:覆盖索引指的是一个查询语句的执行只需要从索引中就能够获取所有需要的数据,而不必回表查询。这样避免了二次查找数据行,从而减少锁持有时间。例如查询语句SELECT user_name FROM users WHERE user_id = 123,如果在user_iduser_name列上创建联合索引,这个查询就可以利用覆盖索引,无需回表,减少锁持有。
  3. 前缀索引:当列值较长时,可使用前缀索引。例如在address列存储用户详细地址,若直接创建索引可能占用过多空间且效率不高,可创建前缀索引CREATE INDEX idx_address ON users (address(10)); ,只对前10个字符创建索引,在一定程度上减少索引空间和查询时间,进而减少锁持有时间。
  4. 避免索引冗余:冗余索引是指多个索引之间存在重复或者包含关系。如已经有索引CREATE INDEX idx_user_name ON users (user_name); ,又创建CREATE INDEX idx_user_name_email ON users (user_name, email); ,其中idx_user_name就是冗余索引。冗余索引会增加索引维护成本,导致锁操作更复杂,所以要避免。