mysql 查询一条语句中,哪些走了索引,并对没走索引的进行优化。

在需要查询的Sql前加上‘EXPLAIN’即可。

示例

某条sql要联调查询4张表,分别为sys_user,sys_user_fs,explicit_number,sys_dept。
他们各自表的索引和字段如下
sys_user:
在这里插入图片描述
sys_user_fs:
在这里插入图片描述
explicit_number:
在这里插入图片描述

sys_dept:
在这里插入图片描述
现在我们执行这条sql语句,来看看用到了哪些索引。

EXPLAIN SELECT
	u.user_id,
	u.dept_id,
	u.user_name,
	u.real_name,
	u.user_type,
	u.user_seat_type,
	u.staff_code,
	u.crm_job_name AS crmJobName,
	u.STATUS,
	u.create_by,
	u.create_time,
	u.update_by,
	u.update_time,
	uf.explicit_number_id,
	uf.explicit_number_id2,
	uf.fs_status,
	uf.seat_type,
	uf.terminal_num,
	SUBSTRING_INDEX( en.explicit_number, 'D5054',- 1 ) AS explicit_number,
	SUBSTRING_INDEX( en2.explicit_number, 'D5054',- 1 ) AS explicit_number2,
	d.dept_name AS crmDeptName 
FROM
	sys_user u
	LEFT JOIN sys_user_fs uf ON u.user_id = uf.user_id
	LEFT JOIN sys_dept d ON u.dept_id = d.dept_id
	LEFT JOIN explicit_number en ON en.id = uf.explicit_number_id
	LEFT JOIN explicit_number en2 ON en2.id = uf.explicit_number_id2
	LEFT JOIN sys_user ucreate ON u.create_by = ucreate.user_name 
WHERE
	u.del_flag = '0' 
	AND u.user_type = '2' 
ORDER BY
	u.create_time DESC 
	LIMIT 10
	
	

在这里插入图片描述
根据显示的信息我们可以看到,'d’表(sys_dept),‘en’表(explicit_number),‘en2’表(explicit_number),‘ucreate’表(sys_user)用到了索引,因为他们的type字段结果为’eq_ref’及’ref’。
‘d’,‘en’,‘en2’的possible_keys字段结果为’PRIMARY’,所以用到的索引分别是主键索引;
‘ucreate’表用到的则是我们自定义的索引,possible_keys字段结果为’index_name’,意味着索引名就为’index_name’,该索引绑定了user_name这个字段。
而’u’表(sys_user)和’uf’表(sys_user_fs)的type字段结果为’ALL’,代表是查询了全部字段,也就是没有用到索引。
在这里插入图片描述

看了上面的分析后,问题就明了了。
在sql语句中,u(sys_user)和uf(sys_user_fs)这两张表是通过各自的user_id字段去连表查询来关联的。
但’u’(sys_user)表中的user_id字段虽然被绑定了索引,但是’uf’(sys_user_fs)表的user_id字段是没有绑定索引的。所以这条sql查询的慢。

在这里插入图片描述

解决方案

1.给uf(sys_user_fs)表的user_id字段绑定索引。
添加索引时,一定要根据该字段在查询语句中的顺序来添加,要注意先后索引字段的顺序
在这里插入图片描述

2.给u(sys_user)表在WHERE查询时用到的字段绑定索引。
此处是根据该表在条件(WHERE)查询时所用到的字段,来绑定对应字段的索引,同样需要两者的顺序保持一致,也就是索引字段的顺序和WHERE条件中所用到的字段顺序要一致。
在这里插入图片描述

场景二:类型不匹配造成的索引失效(未走索引)

有时候很奇怪,明明涉及到的字段加了索引,顺序也一致,但是用EXPLAIN一看就是没走索引,这种情况多半是sql语句中和字段值,和其表中定义的字段类型不匹配造成的。
我们来看一下下面的这个sql语句,就是这个问题。

EXPLAIN SELECT
	t1.id,
	t1.workflow_process_id,
	SUBSTRING_INDEX( t1.explicit_number, 'D5054',- 1 ) AS explicit_number,
	t1.number_type,
	t1.create_time,
	t1.create_by,
	t1.del_flag,
	t1.dept_id,
	t1.style,
	t1.STATUS,
	t1.fs_explicit_id,
	t1.city_code,
	t1.file_path,
	d.dept_name AS org_name,
	t3.opr_time,
CASE
		
		WHEN t3.opr_result = - 1 THEN
		'不通过' 
		WHEN t3.opr_result = 1 THEN
		'通过' 
		WHEN t3.opr_result = 0 THEN
		'审核中' 
	END AS opr_result 
FROM
	explicit_number t1
	LEFT JOIN sys_dept d ON t1.dept_id = d.dept_id
	LEFT JOIN workflow_process t3 ON t1.workflow_process_id = t3.id
	LEFT JOIN sys_user u ON t1.create_by = u.user_name 
WHERE
	t1.del_flag = 0
	and t1.create_time LIKE concat(left('2021-12-15 00:00:00', 10), '%')
	

在这里插入图片描述

通过表结构我们知道,t1(explicit_number)的’del_flag’字段是char类型,但sql语句中使用了 t1.del_flag = 0,也就是判断字段值是否为整数型的0.而非为char字符的0.
所以del_flag字段值本身的类型为char字符类型,但却在sql语句中使用了整数型来判断它是否为0,这也就导致了索引未生效。
正确的用法是改为 t1.del_flag = '0'

正确的则是下面这样:

EXPLAIN SELECT
	t1.id,
	t1.workflow_process_id,
	SUBSTRING_INDEX( t1.explicit_number, 'D5054',- 1 ) AS explicit_number,
	t1.number_type,
	t1.create_time,
	t1.create_by,
	t1.del_flag,
	t1.dept_id,
	t1.style,
	t1.STATUS,
	t1.fs_explicit_id,
	t1.city_code,
	t1.file_path,
	d.dept_name AS org_name,
	t3.opr_time,
CASE
		
		WHEN t3.opr_result = - 1 THEN
		'不通过' 
		WHEN t3.opr_result = 1 THEN
		'通过' 
		WHEN t3.opr_result = 0 THEN
		'审核中' 
	END AS opr_result 
FROM
	explicit_number t1
	LEFT JOIN sys_dept d ON t1.dept_id = d.dept_id
	LEFT JOIN workflow_process t3 ON t1.workflow_process_id = t3.id
	LEFT JOIN sys_user u ON t1.create_by = u.user_name 
WHERE
	t1.del_flag = '0'
	and t1.create_time LIKE concat(left('2021-12-15 00:00:00', 10), '%')
ORDER BY
	t1.create_time DESC 

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/chinatopno1/article/details/121911355
今日推荐