索引失效和sql优化 2020面试必看

索引失效

​ 1.隐式转换导致索引失效.这一点应当引起重视.也是开发中经常会犯的错误.

 由于表的字段tu_mdn定义为varchar2(20),但在查询时把该字段作为number类型以where条件传给Oracle,这样会导致索引失效.

 错误的例子:select * from test where tu_mdn=13333333333;

 正确的例子:select * from test where tu_mdn='13333333333';

 2. 对索引列进行运算导致索引失效,我所指的对索引列进行运算包括(+,-,*,/,! 等)

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

 正确的例子:select * from test where id=10;

 3. 使用Oracle内部函数导致索引失效.对于这样情况应当创建基于函数的索引.

 错误的例子:select * from test where round(id)=10; 说明,此时id的索引已经不起作用了

 正确的例子:首先建立函数索引,create index test_id_fbi_idx on test(round(id));然后 select * from test where round(id)=10; 这时函数索引起作用了

 4. 以下使用会使索引失效,应避免使用;

 a. 使用 <> 、not in 、not exist、!=

 b. like "%_" 百分号在前(可采用在建立索引时用reverse(columnName)这种方法处理)

 c. 单独引用复合索引里非第一位置的索引列.应总是使用索引的第一个列,如果索引是建立在多个列上, 只有在它的第一个列被where子句引用时,优化器才会选择使用该索引。

 d. 字符型字段为数字时在where条件里不添加引号.

 e. 当变量采用的是times变量,而表的字段采用的是date变量时.或相反情况。

 5. 不要将空的变量值直接与比较运算符(符号)比较。

 如果变量可能为空,应使用 IS NULL 或 IS NOT NULL 进行比较,或者使用 ISNULL 函数。

 6. 不要在 SQL 代码中使用双引号。

 因为字符常量使用单引号。如果没有必要限定对象名称,可以使用(非 ANSI SQL 标准)括号将名称括起来。

 7. 将索引所在表空间和数据所在表空间分别设于不同的磁盘chunk上,有助于提高索引查询的效率。

 8. Oracle默认使用的基于代价的SQL优化器(CBO)非常依赖于统计信息,一旦统计信息不正常,会导致数据库查询时不使用索引或使用错误的索引。

 一般来说,Oracle的自动任务里面会包含更新统计信息的语句,但如果表数据发生了比较大的变化(超过20%),可以考虑立即手动更新统计信息,例如:analyze table abc compute statistics,但注意,更新   统计信息比较耗费系统资源,建议在系统空闲时执行。

 9. Oracle在进行一次查询时,一般对一个表只会使用一个索引.

 因此,有时候过多的索引可能导致Oracle使用错误的索引,降低查询效率。例如某表有索引1(Policyno)和索引2(classcode),如果查询条件为policyno = ‘xx’ and classcode = ‘xx’,则系统有可能会使用索   引2,相较于使用索引1,查询效率明显降低。

 10. 优先且尽可能使用分区索引。

 

mysql 最左匹配 联合索引

 

mysql建立多列索引(联合索引)有最左前缀的原则,即最左优先,如:

如果有一个2列的索引(col1,col2),则已经对(col1)、(col1,col2)上建立了索引;如果有一个3列索引(col1,col2,col3),则已经对(col1)、(col1,col2)、(col1,col2,col3)上建立了索引;

总结:1、b+树的数据项是复合的数据结构,比如(name,age,sex)的时候,b+树是按照从左到右的顺序来建立搜索树的,比如当(张三,20,F)这样的数据来检索的时候,b+树会优先比较name来确定下一步的所搜方向,如果name相同再依次比较age和sex,最后得到检索的数据;但当(20,F)这样的没有name的数据来的时候,b+树就不知道第一步该查哪个节点,因为建立搜索树的时候name就是第一个比较因子,必须要先根据name来搜索才能知道下一步去哪里查询。

2、比如当(张三,F)这样的数据来检索时,b+树可以用name来指定搜索方向,但下一个字段age的缺失,所以只能把名字等于张三的数据都找到,然后再匹配性别是F的数据了, 这个是非常重要的性质,即索引的最左匹配特性。(这种情况无法用到联合索引)

 

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

mysql里创建‘联合索引’的意义?

1. "一个顶三个"。建了一个(a,b,c)的复合索引,那么实际等于建了(a),(a,b),(a,b,c)三个索引,因为每多一个索引,都会增加写操作的开销和磁盘空间的开销。对于大量数据的表,这可是不小的开销!

2. 覆盖索引。同样的有复合索引(a,b,c),如果有如下的sql: select a,b,c from table where a=1 and b = 1。那么MySQL可以直接通过遍历索引取得数据,而无需回表,这减少了很多的随机io操作。减少io操作,特别的随机io其实是dba主要的优化策略。所以,在真正的实际应用中,覆盖索引是主要的提升性能的优化手段之一

3. 索引列越多,通过索引筛选出的数据越少。有1000W条数据的表,有如下sql:select * from table where a = 1 and b =2 and c = 3,假设假设每个条件可以筛选出10%的数据,如果只有单值索引,那么通过该索引能筛选出1000W*10%=100w 条数据,然后再回表从100w条数据中找到符合b=2 and c= 3的数据,然后再排序,再分页;如果是复合索引,通过索引筛选出1000w *10% *10% *10%=1w,然后再排序、分页,哪个更高效,一眼便知

 

1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。

2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如:select id from t where num is null可以在num上设置默认值0,确保表中num列没有null值,然后这样查询:select id from t where num=0

3.应尽量避免在 where 子句中使用 or 来连接条件,否则将导致引擎放弃使用索引而进行全表扫描,如:select id from t where num=10 or num=20可以这样查询:select id from t where num=10union allselect id from t where num=20

 

4.in 和 not in 也要慎用,否则会导致全表扫描,如:select id from t where num in(1,2,3)对于连续的数值,能用between 就不要用 in 了:select id from t where num between 1 and 3

很多时候用exists 代替 in 是一个好的选择:select num from a where num in(select num from b)用

下面的语句替换:select num from a where exists(select 1 from b where num=a.num)

 

5.在使用索引字段作为条件时,如果该索引是复合索引,那么必须使用到该索引中的第一个字段作为条件时才能保证系统使用该索引,否则该索引将不会被使用,并且应尽可能的让字段顺序与索引顺序相一致。

6.索引并不是越多越好,索引固然可以提高相应的 select 的效率,但同时也降低了 insert 及 update 的效率,因为insert 或 update 时有可能会重建索引,所以怎样建索引需要慎重考虑,视具体情况而定。一个表的索引数最好不要超过6个,若太多则应考虑一些不常使用到的列上建的索引是否有必要。

7.尽量使用数字型字段,若只含数值信息的字段尽量不要设计为字符型,这会降低查询和连接的性能,并会增加存储开销。这是因为引擎在处理查询和连接时会逐个比较字符串中每一个字符,而对于数字型而言只需要比较一次就够了。

8.不要使用select * from t ,用具体的字段列表代替“*”,不要返回用不到的任何字段。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值