27-06-2018 0 条评论

我们在使用MYSQL的时候,并不是你建立了索引,你执行的SQL语句就一定会走索引,反之当数据量大的时候,走全表扫描,就会出现慢查询,为此我们有方法可以规避这种问题。
首先在这里不得不提下explain,关于它的用法,这里有详细的介绍 EXPLAIN的用法

索引列参与计算

如果where条件中age列中使用了计算,则不会使用该索引

SELECT `*` FROM `user` WHERE `age`=20; // 会使用索引
SELECT `*` FROM `user` WHERE `age`+10=30;// 不会使用索引!!因为所有索引列参与了计算
SELECT `*` FROM `user` WHERE `age`=30-10;//会使用索引

所以需要计算的话,不要放在索引列中,想办法放到右边去。

索引列使用了函数

同样的道理,索引列使用了函数,一样会导致相同的后果

SELECT `*` FROM `user` WHERE concat(`name`,'abc') ='bewynabc'; //不会使用索引,因为使用了函数运算,原理与上面相同
SELECT `*` FROM `user` WHERE `name` =concat('bewyn','abc');  // 会使用索引

索引列使用了Like %XXX

SELECT * FROM `user` WHERE `name` LIKE 'bewyn%'  //走索引
SELECT * FROM `user` WHERE `name` LIKE '%bewyn'  // 不走索引

所以当需要搜索email列中.com结尾的字符串而email上希望走索引时候,可以考虑数据库存储一个反向的内容reverse_email

SELECT * FROM `table` WHERE `reverse_email` LIKE REVERSE('%.com');  // 走索引

注:以上如果你使用REVERSE(email) = REVERSE(‘%.com’),一样得不到你想要的结果,因为你在索引列email列上使用了函数,MySQL不会使用该列索引

同样的,索引列上使用正则表达式也不会走索引。

字符串列与数字直接比较

这是一个坑,假设有一张表,里面的a列是一个字符char类型,且a上建立了索引,你用它与数字类型做比较判断的话:

 SELECT * FROM `user` WHERE `a`='1' //走索引
 SELECT * FROM `user` WHERE `a`=1   //字符串和数字比较,不走索引!

但是如果那个表那个列是一个数字类型,拿来和字符类型的做比较,则不会影响到使用索引

 SELECT * FROM `user` WHERE `b`='1'   //虽然b是数字类型,和'1'比较依然走索引

但是,无论如何,这种额外的隐式类型转换都是开销,而且由于有字符和数字比就不走索引的情况,故建议避免一切隐式类型转换

尽量避免 OR 操作

select * from user where name='bewyn' or address='sh' or phone=137xxx //这样的语句,即使条件中有带索引的列也不会走索引,除非全部建立索引。

所以除非每个列都建立了索引,否则不建议使用OR,在多列OR中,可以考虑用UNION 替换

select * from user where name='bewyn' union
select * from user where address='sh' union
select * from user where phone=137xxx
发表评论

暂无评论,要来一发吗?