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 专门做搜索服务的数据库产品