当系统的吞吐量变大后,数据读写速度会变得原来越慢,因此要想办法对SQL语句进行优化。
避免引擎放弃使用索引而进行全表扫描:
1、对查询进行优化,首先应考虑在 where 及 order by 涉及的列上建立索引
2、应尽量避免在 where 子句中使用!=或<>操作符
3、应尽量避免在 where 子句中对字段进行 null 值判断,如:
select id from t where num is null
可以在num上设置默认值0,确保表中num列没有null值,然后这样查询:
select id from t where num=0
4、尽量避免在 where 子句中使用 or 来连接条件,
例如:
select id from t where num=10 or num=20
可以使用全联查询:
select id from t where num=10
union all
select id from t where num=20
5、like不能前置百分号:
前置百分号将不会使用索引,,但是业务上不可避免可能又需要使用到这种形式。
例如:
select id from t where name like ‘%c%’
若要提高效率,可以使用locate函数或者position函数代替like查询:
可以改为locate(‘c’,name ) > 0或POSITION(‘c’ IN name )>0
6、对于连续的数值,能用 between 就不要用 in
例如:
select id from t where num in(1,2,3)
可以使用下面格式:
select id from t where num between 1 and 3
7、在子查询中,表大用exists,表小用in,等表谁都行。
8、应尽量避免在 where 子句中对字段进行表达式操作
例如:
select id from t where num/2=100
应改为:
select id from t where num=100*2
9、应尽量避免在where子句中对字段进行函数操作
例如:
select id from t where substring(name,1,3)=’abc’–name以abc开头的id
select id from t where datediff(day,createdate,’2005-11-30′)=0–’2005-11-30′生成的id
应改为:
select id from t where name like ‘abc%’
select id from t where createdate>=’2005-11-30′ and createdate<’2005-12-1′
10、不要在where 子句中的“=”左边进行函数、算术运算或其他表达式运算,否则系统将可能无法正确使用索引。
文 末 彩 蛋 : \color{#FF0000}{文末彩蛋:}文末彩蛋:
来自大牛的灵魂拷问:MySQL有什么好优化的?阿里的标准已经说得很清楚了,mysql做好索引就行,不要三表关联,同时控制嵌套子查询的层级不大于二。其他按照阿里的规范来,精力放到前端去处理,横向的扩展前端应用及后端分库。研究这些mysql非索引类的优化是方向性的错误。
有些业务真的复杂,不关联的话,得分批次查询,当查大量数据的时候就得大批量执行sql语句,效率会很低,关联后只需要一次或几次就行,效率会高很多,像这种怎么解决?
复杂业务用oracle,不要用mysql。如果你用mysql处理复杂业务,就必须具备很强的前端应用分布式的能力和后端mysql横向拆分的能力,然而这样的扩展规模受限,因此现在还在这中间插入,增加了中台的概念,把分布式能力加持在中台上,然后由中台向前端去提供服务。总的来说超大规模的业务要省钱省力应该用oracle,花钱买oracle来简化整个架构。
但是如果依然满足不了性能要求,则只能转向前面说的三层架构,那投入的人力物力将是极其巨大的,一般大企业负担不起的。也正因为此,阿里这样的云服务就来廉价的提供现成的弹性云和基础架构来满足业务快速膨胀的企业。对中台这样的三层架构来说,后端集群中的单个数据库并不承担性能上的主要压力,集群中的各个数据库也不需要保持强一致性。整个体系的能力体现在分布式规划上。因此研究mysql单库的性能是方向性的错误,一来不需要掌握这样的技能,二来mysql先天就不适合oltp应用(联机事务处理)。精力应该放在mysql集群方案,拆分方案,异构数据的转换方案上来。
出处:
按照年龄的升序进行排序,如果年龄相同再按照英语成绩降序排列
select name from stus order by age,english desc;
查询 stus 表中 name 以猪开头的且名字长度为3的学生信息
select * from stus where name like ‘猪__’;
A,B两个集合,比如A有3条记录,B有6条,A和B交叉有2条数据
select * from stus,grade;查的是笛卡尔积:18条数据
内连接还有一种隐式的写法,即不需要显示的指定 INNER JOIN 关键字,使用隐式内连接条件的关键字要使用 where 而不再是 on
select grade_name, name from grade,stus where stus.gradeId = grade.id;
left join 是 left outer join 的简写,A left join B等于:3+2=5
right join 是 right outer join 的简写,A right join B等于:2+6=8