1.避免SELECT *
SELECT中每少提取一个字段,数据的提取速度就会有相应的提升。提升的速度还要看舍弃的字段大小来判断。
2.建立索引
根据自己的需求适当建立索引,单个索引或者联合索引。mysql建立联合索引时注意最左匹配原则。
3.避免在列上运算,这样会导致索引失效
1 | SELECT name, score FROM t WHERE score/10 = 9; |
改为
1 | SELECT name, score FROM t WHERE score = 10 * 9; |
4.使用JOIN时
应该用小结果集驱动大结果集,同时把复杂的JOIN查询拆分为多个查询,因为JOIN多个表可能导致更多的锁和堵塞。可以用JOIN代替复杂的字查询。
5.使用LIKE时
避免使用全模糊查询’%%’,因最左匹配这样不会走索引,会全表扫描。
1 | SELECT name, score FROM t WHERE name LIKE '%王%'; |
改为
1 | SELECT name, score FROM t WHERE name LIKE '王%'; |
6. 避免使用null值的判断
null不走索引。 可以给字段一个默认值,比如0。
1 | SELECT name, score FROM t WHERE score IS NULL; |
改为
1 | SELECT name, score FROM t WHERE score = 0; |
7. 避免使用or
or会走全表扫描
1 | SELECT name, score FROM t WHERE score = 30 OR score = 40; |
改为
1 | SELECT name, score FROM t WHERE score = 30 |
8.避免使用in和not in
1 | SELECT name, score FROM t WHERE score IN (2,3); |
优化方式:如果是连续的值,可以用between代替。如下:
1 | SELECT name, score FROM t WHERE score BETWEEN 2 AND 3; |
如果是子查询,可以用exists代替。如下:
1 | SELECT name, score FROM t WHERE EXISTS (SELECT * FROM t1 WHERE t.name = t1.name); |
9.LIMIT
limit基数比较大时,使用between,between限定比limit快,但是between也有缺陷,如果id中间有断行或者是中间有部分id不读取的情况,数据会少
1 | SELECT name, score FROM t WHERE socre = 100 limit 100000, 10; |
改为
1 | SELECT name, score FROM t WHERE socre = 100 BETWEEN 100000 and 100010; |
10.慢sql调优
找到慢sql的原因,是什么引起慢的。可能是查询条件没有索引,或者查询出来的数据量太大。
- 查询条件没有索引
根据查询条件选择最好的索引字段建立索引。即这个字段的值比较分散相对不集中,且这个字段不能有null值,因为字段值集中枚举较少可能数据库引擎不会走索引;索引字段null值,就不会走索引,会全表扫描。 - 数据量太大
如果是查询出来的数据量太大。导致某一个条件的值查询出来的数据量很多,占了整张表数据量的很大一部分。这就需要对数据进行分析,看看能不能通过查询的必选条件建立索引去除很大一部分数据,或者通过某几个条件可以去除大量数据,然后对这几个条件建立联合索引。