数据库运维
记录DBA学习成长历程

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

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

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列建立索引

2.查询结果集是原表中的大部分数据,应该是15%-30%以上。

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

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

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

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

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

5.隐式转换导致索引失效


6.<> ,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'

7.like "%_" 百分号在最前面不走

EXPLAIN SELECT * FROM teltab WHERE telnum LIKE '31%' 走range索引扫描
EXPLAIN SELECT * FROM teltab WHERE telnum LIKE '%110' 不走索引
%linux%类的搜索需求,可以使用elasticsearch+mongodb 专门做搜索服务的数据库产品
赞(1)
MySQL学习笔记 » MySQL不走索引的情况(开发规范)