mysql优化技巧

一、通过连表查询有时候通过子查询先刷选掉一部分数据后再进行查询有时候sql的执行性能会更高。
如下table1先筛掉大量数据后再进行关联查询

SELECT
	* 
FROM
	table1
	LEFT JOIN table2 ON table1.c_table2_id = table2.c_id 
GROUP BY
	table1.c_column1
SELECT
	* 
FROM
	( SELECT * FROM table1 GROUP BY table1.c_column1 ) AS t
	LEFT JOIN table2 ON t.c_table2_id = table2.c_id

以上优化为实际优化的例子。业务需求为:要将table1的多条数据分组并成一条数据导入到新表中(新表涉及到table2的字段)。当然以上sql实际上为简化版(省略了insert语句和其他的一些条件)。按照第一条sql执行了50秒还没执行完。第二条sql执行了1秒多就执行完毕。以上的优化和实际的业务相关。这样子的前提是table1的数据很多,而且条件又可以筛除掉table1的大量数据才能使用这条sql优化。

二、有时候mysql添加冗余条件能够提高查询的性能
怎么叫添加冗余条件呢?这个一般需要与实际的业务场景相结合。比如查询某个部门里某个人今天的考勤状态(t_attendance考勤表,里面有字段人员id、部门id、出勤情况、考勤时间…,索引有组合索引部门id-考勤时间、普通索引人员id)

SELECT
	* 
FROM
	t_attendance 
WHERE
	c_person_id = ***
	AND c_date = '***'

这条sql很明显走的是人员id的索引,但是随着天数的上升,这条sql的性能会越来越差。比如一天生成的考勤数据有四条,那么一位工作了5年的老员工生成的考勤数据就有可能达到40000+的数据(当然只是举个例子,换成网站点击次数会不会让你觉得数据量大一些)这样的的扫描行数明显太多了。
这个时候如果业务里面的参数是有人员的部门id的话那么改写成这样子就很很大的提升性能

SELECT
	* 
FROM
	t_attendance 
WHERE
	c_person_id = ***
	AND c_department_id = ***
	AND c_date = '***'

由于部门里面的人数是有限的,而且只查一天走了组合索引部门id-考勤时间。因此扫描行数就有可能变成部门人数*4。
当然,如果你拿不到部门id或者觉得将普通索引人员id改为组合索引人员id-考勤时间后这条索引的使用率会很高,那么就改成组合索引人员id-考勤时间吧。(添加的索引列越多,数据做更新、删除、插入操作的性能越低,因为需要重建索引)
可能上面的例子需要很结合业务,可能看的不是很懂。那么比如相亲网站需要经常查询性别和年龄。于是原先创建了组合索引“性别-年龄”。(ps:虽然索引的区分度不高,但是有时候如果使用的频率高的话可以创建,如下图解释)

在这里插入图片描述
引用自《高性能mysql》5.4.1

而现在添加了一个需要了,我只要筛选年龄的,不需要筛选性别了,那怎么办。

SELECT
	* 
FROM
	t_people 
WHERE
	c_sex IN ( '男', '女' ) 
	AND c_age = ***

这样子因为添加了一个条件就用上索引了

三、时刻注意sql语句中的or

CREATE TABLE `t` (
  `id` int(11) NOT NULL,
  `a` int(11) DEFAULT NULL,
  `b` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
) ENGINE=InnoDBdelimiter ;;
create procedure idata()
begin
  declare i int;
  set i=1;
  while(i<=1000000)do
    insert into t values(i, i, i);
    set i=i+1;
  end while;
end;;
delimiter ;
call idata();

1.组合索引的情况下使用or。
例:索引:idx_a_b 查询条件只有“a or b”
结论:索引生效,但是实际效果和全表扫描一样。
分析:因为系统需要分别扫描字段b和a,而字段b无法生效索引(组合索引的最左前缀),所以必须全表扫描一下字段b。至于为什么明明是全表扫描,但是explain显示生效了索引,我也不是很明白,统计了一下时间其实是和不使用索引,全表扫描的时间是一致的

2.or字段都带有单列索引
例:索引:idx_a, idx_b 查询条件只有“a or b”
结论:索引生效,使用索引混合的方式(index_merge)
分析:因为系统需要分别扫描字段b和a,刚好又a和b分别的单列索引,所以系统分开扫描,分别扫描了a和b的索引,最后将结合融合。
注意:a可能扫描的某行和b扫描的某行是一致的(如:a = 5, b = 5),a扫过该行后,b仍然会扫描该行,最终扫描的行数是2

3.or字段不都带有单列索引
例:索引:idx_a 查询条件“a or id or b”
结论:索引不生效,全表扫描
分析:因为系统需要分别扫描字段b和a和id,id和a都有单列索引,b没有,系统必须去全表扫描发现符合b的情况。因此索引不生效。

4.连表情况下在where子句中的or

CREATE TABLE `t2` (
  `id` int(11) NOT NULL,
  `c` int(11) DEFAULT NULL,
  `d` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
) ENGINE=InnoDB-- 自己随便插一些数据吧

在讲这个之前必须先明白连表的过程:先过一下where子句,然后将得到的结果根据根据ON里面的条件进行融合。
那么在where子句中的or情况又分为下面的几种情况
①or的字段都是在单个表中,参考上面的三种情况
②or的字段在多个表中,我们可以发现索引不生效
索引:单列索引a,b,c

SELECT * FROM t LEFT JOIN t2 ON t.id = t2.id  WHERE t.a = 5 OR t.b = 5 OR t2.c = 5

分析:由于是跨表or where条件是无法判断刷选之后再连表的结果是正确的

t.idt2.idabc
555
665
775

如上面查询语句本来是要查询id等于5,6,7的情况,但是如果是先用where刷选t表的话是选出了id等于5和6的情况,t2表是id等于5的情况,那么结果就是id等于6,7但是c字段都为null的情况,所以与预期不符,所以他的实际查询过程应该是先做全表扫描并根据on左连,然后再过where条件,但实际上连表后是一个新的表,所以不会用到索引。
解决办法:很头疼,用不上索引了,那有扫描办法呢?试试这条语句

SELECT * FROM t LEFT JOIN t2 ON t.id = t2.id  WHERE t.a = 5 OR t.b = 5
UNION
SELECT * FROM t LEFT JOIN t2 ON t.id = t2.id  WHERE t2.c = 5

确保了or字段没有跨表,用上了索引,然后再将两次的条件加一下,再去重,就可以得出正确结果了。
如果你的结果可以不用去重,那么用上UNION ALL代替UNION效率会更高

四、用SHOW INDEX FROM t_table查看索引的区分度
我们创建索引需要保证的基本原则是区分度要高那么怎么看效果呢?SHOW INDEX FROM t_table看帮你查看已创建了的索引的区分度情况

五、update/delete条件筛选一定要加上索引,不然即使更新一行数据也会锁表
自己可以试一下
表t(id,c, d)

-- 会话1,开启事物,并不要提交事物
BEGIN;
	UPDATE t 
	SET a = 1 
WHERE
	b = 1;
-- 会话2
UPDATE t 
SET a = 2 
WHERE
	b =2

会话2会阻塞,直到会话1提交了事物,这证明会话1的操作锁了整个表。如果加上索引就会退化成行锁或者间隙锁

六、update和delete语句后面尽量加limit,知道结果为1条的也要加上limit。
加limit有两个好处:
1、防止误删或误更新数据。
2、减小间隙锁的锁区间,减少查询要遍历的行数(详情可看mysql语句执行中的锁情况)。

七、group by后面的字段要尽量使用上索引
这里有两点可以注意一下:
1、单表才能用上group by后面字段的索引,多表的话要看mysql的优化器选择了哪个表做为驱动表
2、group by无法加索引优化,且不需要排序的情况下,在group by后面加order by null会有奇效

1、单表才能用上group by后面字段的索引,多表的话要看mysql的优化器选择了哪个表做为驱动表
例:(t(id, c)t2(id, c))

-- 注意mysql的优化器不一定会按照你左联或者右连来选择驱动表,可以用SHOW WARNINGS来看优化器的执行计划
-- 驱动表t2
SELECT
	t.a 
FROM
	t
	RIGHT JOIN t2 ON t2.c = t.a
GROUP BY
	t.a;
-- 驱动表t
SELECT
	t.a 
FROM
	t
	LEFT JOIN t2 ON t2.c = t.a 
GROUP BY
	t.a

explain的结果
t2做为驱动表
在这里插入图片描述
t为驱动表
![在这里插入图片描述](https://img-blog.csdnimg.cn/20190925170358384.png

除了上面的方法,还可以

SELECT
	tt.a 
FROM
	( SELECT t.a FROM t GROUP BY t.a ) tt 
	RIGHT JOIN t2 ON t2.c = tt.a

在这里插入图片描述
但是可明显也多了张临时表,所以如果结合开篇的第一点就会有很大的性能提升。
2、group by无法加索引优化,且不需要排序的情况下,在group by后面加order by null会有奇效。

SELECT
	t.c 
FROM
	t
	RIGHT JOIN t2 ON t2.c = t.c 
GROUP BY
	t.c 
ORDER BY NULL

在这里插入图片描述
我们看到少了排序操作,原因是group by后默认按group by的字段进行排序,使用order by null就告诉mysql说我不需要排序

八、简单的查看索引的执行情况(innodb)

SELECT * FROM `performance_schema`.`table_io_waits_summary_by_index_usage`

详细可看mysql查看索引执行情况

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
众所周知,人工智能是当前最热门的话题之一, 计算机技术与互联网技术的快速发展更是将对人工智能的研究推向一个新的高潮。 人工智能是研究模拟和扩展人类智能的理论与方法及其应用的一门新兴技术科学。 作为人工智能核心研究领域之一的机器学习, 其研究动机是为了使计算机系统具有人的学习能力以实现人工智能。 那么, 什么是机器学习呢? 机器学习 (Machine Learning) 是对研究问题进行模型假设,利用计算机从训练数据中学习得到模型参数,并最终对数据进行预测和分析的一门学科。 机器学习的用途 机器学习是一种通用的数据处理技术,其包含了大量的学习算法。不同的学习算法在不同的行业及应用中能够表现出不同的性能和优势。目前,机器学习已成功地应用于下列领域: 互联网领域----语音识别、搜索引擎、语言翻译、垃圾邮件过滤、自然语言处理等 生物领域----基因序列分析、DNA 序列预测、蛋白质结构预测等 自动化领域----人脸识别、无人驾驶技术、图像处理、信号处理等 金融领域----证券市场分析、信用卡欺诈检测等 医学领域----疾病鉴别/诊断、流行病爆发预测等 刑侦领域----潜在犯罪识别与预测、模拟人工智能侦探等 新闻领域----新闻推荐系统等 游戏领域----游戏战略规划等 从上述所列举的应用可知,机器学习正在成为各行各业都会经常使用到的分析工具,尤其是在各领域数据量爆炸的今天,各行业都希望通过数据处理与分析手段,得到数据中有价值的信息,以便明确客户的需求和指引企业的发展。
众所周知,人工智能是当前最热门的话题之一, 计算机技术与互联网技术的快速发展更是将对人工智能的研究推向一个新的高潮。 人工智能是研究模拟和扩展人类智能的理论与方法及其应用的一门新兴技术科学。 作为人工智能核心研究领域之一的机器学习, 其研究动机是为了使计算机系统具有人的学习能力以实现人工智能。 那么, 什么是机器学习呢? 机器学习 (Machine Learning) 是对研究问题进行模型假设,利用计算机从训练数据中学习得到模型参数,并最终对数据进行预测和分析的一门学科。 机器学习的用途 机器学习是一种通用的数据处理技术,其包含了大量的学习算法。不同的学习算法在不同的行业及应用中能够表现出不同的性能和优势。目前,机器学习已成功地应用于下列领域: 互联网领域----语音识别、搜索引擎、语言翻译、垃圾邮件过滤、自然语言处理等 生物领域----基因序列分析、DNA 序列预测、蛋白质结构预测等 自动化领域----人脸识别、无人驾驶技术、图像处理、信号处理等 金融领域----证券市场分析、信用卡欺诈检测等 医学领域----疾病鉴别/诊断、流行病爆发预测等 刑侦领域----潜在犯罪识别与预测、模拟人工智能侦探等 新闻领域----新闻推荐系统等 游戏领域----游戏战略规划等 从上述所列举的应用可知,机器学习正在成为各行各业都会经常使用到的分析工具,尤其是在各领域数据量爆炸的今天,各行业都希望通过数据处理与分析手段,得到数据中有价值的信息,以便明确客户的需求和指引企业的发展。
众所周知,人工智能是当前最热门的话题之一, 计算机技术与互联网技术的快速发展更是将对人工智能的研究推向一个新的高潮。 人工智能是研究模拟和扩展人类智能的理论与方法及其应用的一门新兴技术科学。 作为人工智能核心研究领域之一的机器学习, 其研究动机是为了使计算机系统具有人的学习能力以实现人工智能。 那么, 什么是机器学习呢? 机器学习 (Machine Learning) 是对研究问题进行模型假设,利用计算机从训练数据中学习得到模型参数,并最终对数据进行预测和分析的一门学科。 机器学习的用途 机器学习是一种通用的数据处理技术,其包含了大量的学习算法。不同的学习算法在不同的行业及应用中能够表现出不同的性能和优势。目前,机器学习已成功地应用于下列领域: 互联网领域----语音识别、搜索引擎、语言翻译、垃圾邮件过滤、自然语言处理等 生物领域----基因序列分析、DNA 序列预测、蛋白质结构预测等 自动化领域----人脸识别、无人驾驶技术、图像处理、信号处理等 金融领域----证券市场分析、信用卡欺诈检测等 医学领域----疾病鉴别/诊断、流行病爆发预测等 刑侦领域----潜在犯罪识别与预测、模拟人工智能侦探等 新闻领域----新闻推荐系统等 游戏领域----游戏战略规划等 从上述所列举的应用可知,机器学习正在成为各行各业都会经常使用到的分析工具,尤其是在各领域数据量爆炸的今天,各行业都希望通过数据处理与分析手段,得到数据中有价值的信息,以便明确客户的需求和指引企业的发展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值