一、避免不使用索引的情况
1、Like的参数以通配符开头时
-- 不走索引
select * from t_credit_detail where Flistid like '%0';
-- 走索引
select * from t_credit_detail where Flistid like '0%';
非要用 like ‘%0’ 的形式走索引的解决方案是使用覆盖索引来解决。
2、where条件不符合最左前缀原则时
创建了一个联合索引idx_t1_bcd(a,b,c)
where a = 1 and b = 2; -- 走索引
where b = 2 and c = 3 and a = 1; -- 走索引(mysql的查询优化器会帮你优化成索引可以识别的形式。)
where b = 2; -- 不走索引
3、使用!= 或 <> 操作符时
尽量避免使用!= 或 <>操作符,否则数据库引擎会放弃使用索引而进行全表扫描。使用>或<会比较高效。
4、索引列参与计算
where a + 1 > 2; -- 不走索引
5、对字段进行null值判断
应尽量避免在where子句中对字段进行null值判断,否则将导致引擎放弃使用索引而进行全表扫描,如:
where Flistid is null; -- 不走索引
-- 可以在Flistid上设置默认值0,确保表中Flistid列没有null值,然后这样查询:
where Flistid = 0; -- 走索引
6、使用or来连接条件
应尽量避免在where子句中使用or来连接条件,否则将导致引擎放弃使用索引而进行全表扫描,如:
where a = 1 or a = 2; -- 不走索引
-- 可以用下面这样的查询代替上面的 or 查询:
select id from t1 where a = 1 union all select id from t1 where a = 2 ; -- 走索引
其他写法
1、避免select *
在解析的过程中,会将’*’ 依次转换成所有的列名,这个工作是通过查询数据字典完成的,这意味着将耗费更多的时间。
2、order by 语句优化
任何在Order by语句的非索引项或者有计算表达式都将降低查询速度。
- 重写order by语句以使用索引
- 为所使用的列建立另外一个索引
- 绝对避免在order by子句中使用表达式。
3、GROUP BY语句优化
将不需要的记录在GROUP BY 之前过滤掉,先GROUP BY,再HAVING
4、用 exists 代替 in
WHERE id IN (SELECT id FROM class_b);
WHERE exists (SELECT * FROM class_b WHERE class_b.id = class_a.id)
- 如果连接列id 上有索引,那么查询CLASS_B时,无需查询实际表,仅需要查索引就可以了。
- 使用exists,那么只有查到一行数据满足条件就会终止查询,不会产生临时表。
- 使用in查询时,数据库首先会执行子查询,然后将结果保存在临时表中,然后扫描整个临时表,很多情况下非常耗费资源。
5、能用DISTINCT的就不用GROUP BY
SELECT id from table_a group by id;
SELECT DISTINCT id from table_a;
6、能用UNION ALL就不要用UNION
UNION ALL不执行SELECT DISTINCT函数,这样就会减少很多不必要的资源。
7、在Join表的时候使用相当类型的例,并将其索引
如果应用程序有很多JOIN 查询,你应该确认两个表中Join的字段是被建过索引的。这样,MySQL内部会启动为你优化Join的SQL语句的机制。
而且,这些被用来Join的字段,应该是相同的类型的。例如:如果你要把 DECIMAL 字段和一个 INT 字段Join在一起,MySQL就无法使用它们的索引。对于那些STRING类型,还需要有相同的字符集才行。(两个表的字符集有可能不一样)