DevOps开发运维
成长之路

MySQL不走索引的情况(DBA开发规范)

没有查询条件,或者查询条件没有建立索引

select * from tab; 全表扫描。
select * from tab where 1=1;
在业务数据库中,特别是数据量比较大的表。是没有全表扫描这种需求。
1、对用户查看是非常痛苦的。
2、对服务器来讲毁灭性的。
select * from tab;SQL改写成以下语句:
(1)select * from tab order by price limit 10 ; 需要在price列上建立索引
(2)select * from tab where name='zhangsan' ; name列没有索引
改:
1、换成有索引的列作为查询条件
2、将name列建立索引

查询结果集是原表中的大部分数据,应该是25%以上。

查询的结果集,超过了总数行数25%,优化器觉得就没有必要走索引了。
假如:tab表 id,name其中id:1-100w,id列有(辅助)索引
select * from tab where id>500000;如果业务允许,可以使用limit,between and等控制,尽量减少结果集显示。
怎么改写 ?
结合业务判断,有没有更好的方式。如果没有更好的改写方案,却是需要拿数据做计算和处理,统计
尽量不要在mysql存放这个数据了。放到redis里面。

索引本身失效,统计数据不真实

索引有自我维护的能力。
对于表内容变化比较频繁的情况下,有可能会出现索引失效。
现象:
有一条select语句平常查询时很快,突然有一天很慢,会是什么原因
select? -->索引失效,统计数据不真实,一般是先查看是否有索引,processlist,kill临时解决,索引分析删除重建
DML事务语句? -->锁冲突(语句做操作,其他语句必须等待)

查询条件使用函数在索引列上,或者对索引列进行运算,运算包括(+,-,*,/,! 等)

例子:
错误的例子:select * from test where id-1=9;
正确的例子:select * from test where id=10;

隐式转换导致索引失效


<> ,not in 不走索引(辅助索引)

EXPLAIN SELECT * FROM teltab WHERE telnum <> '110';
EXPLAIN SELECT * FROM teltab WHERE telnum NOT IN ('110','119');
单独的>,<,in 有可能走,也有可能不走,和结果集有关,尽量结合业务添加limit
or或in 尽量改成union all
EXPLAIN SELECT * FROM teltab WHERE telnum IN ('110','119');
改写成:
EXPLAIN SELECT * FROM teltab WHERE telnum='110'
UNION ALL
SELECT * FROM teltab WHERE telnum='119'

like “%_” 百分号在最前面不走

EXPLAIN SELECT * FROM teltab WHERE telnum LIKE '31%' 走range索引扫描
EXPLAIN SELECT * FROM teltab WHERE telnum LIKE '%110' 不走索引
%linux%类的搜索需求,可以使用elasticsearch+mongodb 专门做搜索服务的数据库产品
赞(1)

评论 抢沙发

评论前必须登录!

 

LNMP社群 不仅仅是技术

关于我们网站地图