网站首页 > 基础教程 正文
问题导读
一、哪些情况下索引会失效?
二、说一下varchar与char的区别吧
三、做过SQL优化吗?请举几个例子说明一下
一、哪些情况下索引会失效?
正经回答:
1、在字段开头模糊查询
如下:
SELECT * FROM t WHERE username LIKE '%陈%'
优化方式:尽量在字段后面使用模糊查询。
SELECT * FROM t WHERE username LIKE '陈%'
如果需求是要在前面使用模糊查询:
- 使用MySQL内置函数INSTR(str,substr) 来匹配,作用类似于java中的indexOf(),查询字符串出现的角标位置,可参阅《MySQL模糊查询用法大全(正则、通配符、内置函数等)》
- 使用FullText全文索引,用match against 检索
- 数据量较大的情况,建议引用ElasticSearch、solr,亿级数据量检索速度秒级
- 当表数据量较少(几千条儿那种),别整花里胡哨的,直接用like ‘%xx%’。
2、使用 or
如下:
SELECT * FROM t WHERE id = 1 OR id = 3
优化方式:可以用union代替or。如下:
SELECT * FROM t WHERE id = 1
UNION
SELECT * FROM t WHERE id = 3
3、进行null值判断
如下:
SELECT * FROM t WHERE score IS NULL
优化方式:可以给字段添加默认值0,对0值进行判断。如下:
SELECT * FROM t WHERE score = 0
分享一下,你的朋友可能正需要它!!!
4、在where条件中=号的左侧进行表达式、函数操作
可以将表达式、函数操作移动到等号右侧。如下:
-- 全表扫描
SELECT * FROM T WHERE score/10 = 9
-- 走索引
SELECT * FROM T WHERE score = 10*9
5、使用where 1=1的条件
如下:
SELECT username, age, sex FROM T WHERE 1=1
优化方式:用代码拼装sql时进行判断,没 where 条件就去掉 where,有where条件就加 and。
6、查询条件用 <> 或者 !=
使用索引列作为条件进行查询时,需要避免使用<>或者!=等判断条件。
如确实业务需要,使用到不等于符号,需要在重新评估索引建立,避免在此字段上建立索引,改由查询条件中其他索引字段代替。
7、where条件仅包含复合索引非前置列
如下:复合(联合)索引包含key_part1,key_part2,key_part3三列,但SQL语句没有包含索引前置列"key_part1",按照MySQL联合索引的最左匹配原则,不会走联合索引。
select col1 from table where key_part2=1 and key_part3=2
8、隐式类型转换造成不使用索引
如下SQL语句由于索引对列类型为varchar,但给定的值为数值,涉及隐式类型转换,造成不能正确走索引。
select col1 from table where col_varchar=123;
9、order by 条件要与where中条件一致,否则order by不会利用索引进行排序
-- 不走age索引
SELECT * FROM t order by age;
-- 走age索引
SELECT * FROM t where age > 0 order by age;
对于上面的语句,数据库的处理顺序是:
第一步:根据where条件和统计信息生成执行计划,得到数据。
第二步:将得到的数据排序。当执行处理数据(order by)时,数据库会先查看第一步的执行计划,看order by 的字段是否在执行计划中利用了索引。如果是,则可以利用索引顺序而直接取得已经排好序的数据。如果不是,则重新进行排序操作。
第三步:返回排序后的数据。
当order by 中的字段出现在where条件中时,才会利用索引而不再二次排序,更准确的说,order by 中的字段在执行计划中利用了索引时,不用排序操作。
这个结论不仅对order by有效,对其他需要排序的操作也有效。比如group by 、union 、distinct等。
二、说一下varchar与char的区别吧
正经回答:
char
- char表示定长字符串,长度是固定的;
- 如果插入数据的长度小于char的固定长度时,则用空格填充;
- 因为长度固定,所以存取速度要比varchar快很多,甚至能快50%,但正因为其长度固定,所以会占据多余的空间,是空间换时间的做法;
- 对于char来说,最多能存放的字符个数为255,和编码无关
varchar
- varchar表示可变长字符串,长度是可变的;
- 插入的数据是多长,就按照多长来存储;
- varchar在存取方面与char相反,它存取慢,因为长度不固定,但正因如此,不占据多余的空间,是时间换空间的做法;
- 对于varchar来说,最多能存放的字符个数为65532
三、做过SQL优化吗?几个请举例子说明一下
正经回答:
重复查询相同的数据:可以缓存数据,下次直接读取缓存
一个复杂查询还是多个简单查询
MySQL内部每秒能扫描内存中上百万行数据,相比之下,响应数据给客户端就要慢得多
使用尽可能小的查询是好的,但是有时将一个大的查询分解为多个小的查询是很有必要的。
切分查询
将一个大的查询分为多个小的相同的查询
一次性删除1000万的数据要比一次删除1万,暂停一会的方案更加损耗服务器开销。
分解关联查询,让缓存的效率更高。
UNION ALL的效率高于UNION
每日小结
今天我们复习了面试中常考的数据库三个问题,你做到心中有数了么?
对了,**如果你的朋友也在准备面试,请将这个系列扔给他,如果他认真对待,肯定会感谢你的!!**
好了,今天就到这里,学废了的同学,`记得三连,也会给我继续更新的动力。`
- 上一篇: java如何调用支付宝和微信支付功能
- 下一篇: java实现10种排序算法
猜你喜欢
- 2024-11-30 java实现10种排序算法
- 2024-11-30 java如何调用支付宝和微信支付功能
- 2024-11-30 java常见异常机制
- 2024-11-30 Java性能优化的50个细节,我必须分享给你
- 2024-11-30 JAVA常见异常
- 2024-11-30 你还在遍历搜索集合?别逗了!Java 8 一行代码搞定,是真的优雅
- 2024-11-30 「Java面试题第一期」Java常见异常有哪些?
- 2024-11-30 灵魂拷问:如何检查Java数组中是否包含某个值?
- 2024-11-30 java面试题
- 2024-11-30 我把Java基础编程及思维导图整理的超级详细,小白都能看懂
- 最近发表
- 标签列表
-
- gitpush (61)
- pythonif (68)
- location.href (57)
- tail-f (57)
- pythonifelse (59)
- deletesql (62)
- c++模板 (62)
- css3动画 (57)
- c#event (59)
- linuxgzip (68)
- 字符串连接 (73)
- nginx配置文件详解 (61)
- html标签 (69)
- c++初始化列表 (64)
- exec命令 (59)
- canvasfilltext (58)
- mysqlinnodbmyisam区别 (63)
- arraylistadd (66)
- node教程 (59)
- console.table (62)
- c++time_t (58)
- phpcookie (58)
- mysqldatesub函数 (63)
- window10java环境变量设置 (66)
- c++虚函数和纯虚函数的区别 (66)