原文:链接:https://www.jianshu.com/p/06948343681b
1.框架自带的模型查询比原生的sql要慢
2.应尽量避免在 where 子句中使用 != 或 <> 操作符,否则将引擎放弃使用索引而进行全表扫描
对于上面两条sql来说
id != 6055 的sql执行时间为0.548秒
id>6055 or id<6055 的sql执行时间为0.0016秒
3.in 和 not in 也要慎用,否则会导致全表扫描
如下图所示:lx_com表是一个千万级数据量的表,ids表是一个只有三个值的表。我们执行如下sql发现耗时19.78秒。
这是因为:
select id,name from lx_com where id in (select id from ids)
并不等价于
select id,name from lx_com where id in (3,5,7)
当我们执行 select id,name from lx_com where id in (select id from ids)时候,mysql会变量lx_com 表中上千万的数据,并一一判断是否在select id from ids的范围内,而不是我们平常所想象的先执行select id from ids,再进行外层查询。
这时候,我们再试一下关联查询,就会发现时间仅用0.01s
4.对于连续的数值,能用 between 就不要用 in :
$sql1 ="select id from `dye_production_schedules` where product_id in (2401,2402.2403)";
$sql2 ="select id from `dye_production_schedules` where product_id between 2400 and 2404";
5.count优化:
6.%abc%的查询将导致全表扫描
7.sql子句中尽量不要进行函数操作,表达式操作
8.尽可能的使用 varchar 代替 char
因为首先变长字段存储空间小,可以节省存储空间,其次对于查询来说,在一个相对较小的字段内搜索效率显然要高些。
9.尽量不要给数据库留NULL,尽可能的使用 NOT NULL填充数据库
对于varchar 字段来说 null 是不占用任何空间的,查询起来反而还要快
但是对于char(100)来说,哪怕是null也会占用100字节空间
10.任何地方都不要使用 select * from t ,用具体的字段列表代替“*”,不要返回用不到的字段。
11.尽量避免向客户端返回大数据量,若数据量过大,可分批处理
例1:批量处理数据(可分批向缓存中存贮)避免数组盛放过多的数据 给服务器造成巨大的压力
例2:大批量数据关联查找我们可以查出主键值,将主键值的数组分成小块,每次只处理小块内的数据
12.应尽量避免在 where 子句中使用 or 来连接条件,如果一个字段有索引,一个字段没有索引,将导致引擎放弃使用索引而进行全表扫描
13.尽量使用union all替换union
因为union all不过滤,效率高(union去重代价非常高,尽可能的放在程序中去重)
14.能够用DISTINCT的就不用GROUP BY
15.大数据量的limit操作
原文地址:Mysql limit 优化,百万至千万级快速分页 复合索引
16.向数据库中插入多条数据,拼接成一条sql语句最快
17.ORDER BY语句的MySQL优化
①ORDER BY + LIMIT组合的索引优化
SELECT [column1],[column2],…. FROM [TABLE] ORDER BY [sort] LIMIT [offset],[LIMIT];
这个SQL语句优化比较简单,在[sort]这个栏位上建立索引即可。
②WHERE + ORDER BY + LIMIT组合的索引优化
SELECT [column1],[column2],…. FROM [TABLE] WHERE [columnX] = [VALUE] ORDER BY [sort] LIMIT [offset],[LIMIT];
这个语句,如果你仍然采用第一个例子中建立索引的方法,虽然可以用到索引,但是效率不高。更高效的方法是建立一个联合索引(columnX,sort)
③WHERE + IN + ORDER BY + LIMIT组合的索引优化
SELECT [column1],[column2],…. FROM [TABLE] WHERE [columnX] IN ([value1],[value2],…) ORDER BY [sort] LIMIT [offset],[LIMIT];
这个语句如果你采用第二个例子中建立索引的方法,会得不到预期的效果(仅在[sort]上是using index,WHERE那里是using where;using filesort),理由是这里对应columnX的值对应多个。
④WHERE+ORDER BY多个栏位+LIMIT
SELECT * FROM [table] WHERE uid=1 ORDER x,y LIMIT 0,10;
对于这个语句,大家可能是加一个这样的索引:(x,y,uid)。但实际上更好的效果是(uid,x,y)。这是由MySQL处理排序的机制造成的。
18.合理使用EXISTS,NOT EXISTS子句
1.SELECT SUM(T1.C1) FROM T1 WHERE (SELECT COUNT(*)FROM T2 WHERE T2.C2=T1.C2>0)
2.SELECT SUM(T1.C1) FROM T1 WHERE EXISTS(SELECT * FROM T2 WHERE T2.C2=T1.C2)
上面两条sql产生相同的结果,但是后者的效率显然要高于前者。因为后者不会产生大量锁定的表扫描或是索引扫描。如果你想校验表里是否存在某条纪录,不要用count(*) > 0 那样效率很低,而且浪费服务器资源。可以用EXISTS代替。
19. 尽量不要用SELECT INTO语句。SELECT INTO 语句会导致表锁定,阻止其他用户访问该表。
SELECT INTO 语句从一个表中选取数据,然后把数据插入另一个表中,常用于创建表的备份复件或者用于对记录进行存档。