一: 面试题
Q1: Mysql的索引原理和数据结构简单介绍下?
Q2: B+树和B树的区别是什么?
Q3: mysql的聚簇索引和非聚簇索引的区别?
Q4: 使用Mysql索引都有什么原则?
Q5: 不同的存储引擎是如何进行实际存储的?
Q6: 不同的组合索引的结构是什么样的?
Q7: mysql所有如何进行优化?
1、mysql分页有什么优化
2、悲观锁、乐观锁
3、组合索引,最左原则
4、mysql 的表锁、行锁
5、mysql 性能优化
6、mysql的索引分类:B+,hash;什么情况用什么索引
7、事务的特性和隔离级别
1.mysql 中查询条件使用In查询 会走索引吗
一、IN 是否会走索引?
1. 单列索引场景
如果字段有索引,且 IN 中的值数量合理,通常会走索引。
示例:
– user_id 是索引字段
SELECT * FROM users WHERE user_id IN (1, 2, 3);
优化器会将 IN 转换为多个 OR 条件,并走索引(执行计划显示 type=range)。
2. 复合索引场景
如果 IN 作用在复合索引的 最左前缀字段 上,可能走索引。
示例:
-- 复合索引 (age, city)
SELECT * FROM users WHERE age IN (20, 25) AND city = 'Beijing';
age 是索引的最左字段,会走索引(type=range)。
如果 IN 作用在非最左字段(如 city),则不会走索引。
二、IN 不走索引的常见情况
1. IN 列表参数过多
如果 IN 中的值数量过大(如超过表记录的 20%~30%),优化器可能认为全表扫描更快。
-- 假设表中 50% 的记录的 status 是 1 或 2
SELECT * FROM orders WHERE status IN (1, 2);
执行计划可能显示 type=ALL(全表扫描)。
2. 数据分布不均
如果索引字段的值重复率高(低选择性),优化器可能跳过索引。
-- gender 字段只有 'M'/'F' 两个值
SELECT * FROM users WHERE gender IN ('M');
- 索引未覆盖查询字段
如果查询字段未完全被索引覆盖,可能回表代价过高,导致优化器放弃索引。
-- 索引是 (user_id)
SELECT name, email FROM users WHERE user_id IN (1, 2, 3);
虽然 user_id 走索引,但需要回表查询 name 和 email,可能仍选择全表扫描。
三、如何验证是否走索引?
使用 EXPLAIN 分析 SQL 执行计划:
EXPLAIN SELECT * FROM users WHERE user_id IN (1, 2, 3);
关键字段说明:
type:range 表示范围扫描(走索引),ALL 表示全表扫描。
key:显示实际使用的索引名称。
rows:预估扫描的行数。
四、优化 IN 查询的实践方案
1. 控制 IN 的参数数量
若 IN 列表过长,分批次查询:
-- 分批次查询(每次查 100 个)
SELECT * FROM users WHERE user_id IN (1, 2, ..., 100);
SELECT * FROM users WHERE user_id IN (101, 102, ..., 200);
2. 使用覆盖索引
确保查询字段全部在索引中,避免回表:
-- 创建覆盖索引 (user_id, name, email)
CREATE INDEX idx_user_info ON users (user_id, name, email);
– 查询时直接走索引
SELECT user_id, name, email FROM users WHERE user_id IN (1, 2, 3);
3. 临时表或 JOIN 优化
对超大的 IN 列表,改用临时表或 JOIN:
-- 创建临时表存储 ID
CREATE TEMPORARY TABLE temp_ids (id INT PRIMARY KEY);
INSERT INTO temp_ids VALUES (1), (2), (3);
-- 通过 JOIN 查询
SELECT u.*
FROM users u
JOIN temp_ids t ON u.user_id = t.id;
4. 调整优化器策略
强制使用索引(慎用):
SELECT * FROM users FORCE INDEX (idx_user_id)
WHERE user_id IN (1, 2, 3);