转载

MySQL在 5.0版本中引入新特性:索引合并优化(Index merge optimization),当查询中单张表可以使用多个索引时,同时扫描多个索引并将扫描结果进行合并。

该特新主要应用于以下三种场景:

1、      对OR语句求并集,如查询SELECT * FROM TB1 WHERE c1="xxx" OR c2=""xxx"时,如果c1和c2列上分别有索引,可以按照c1和c2条件进行查询,再将查询结果合并(union)操作,得到最终结果

2、      对AND语句求交集,如查询SELECT * FROM TB1 WHERE c1="xxx" AND c2=""xxx"时,如果c1和c2列上分别有索引,可以按照c1和c2条件进行查询,再将查询结果取交集(intersect)操作,得到最终结果

3、      对AND和OR组合语句求结果

该新特性可以在一些场景中大幅度提升查询性能,但受限于MySQL糟糕的统计信息,也导致很多场景查询性能极差甚至导致数据库崩溃。

以SELECT * FROM TB1 WHERE c1="xxx" AND c2=""xxx" 为例:

1、      当c1列和c2列选择性较高时,按照c1和c2条件进行查询性能较高且返回数据集较小,再对两个数据量较小的数据集求交集的操作成本也较低,最终整个语句查询高效;

2、      当c1列或c2列选择性较差且统计信息不准时,比如整表数据量2000万,按照c2列条件返回1500万数据,按照c1列返回1000条数据,此时按照c2列条件进行索引扫描+聚集索引查找的操作成本极高(可能是整表扫描的百倍消耗),对1000条数据和1500万数据求交集的成本也极高,最终导致整条SQL需要消耗大量CPU和IO资源且相应时间超长,而如果值使用c1列的索引,查询消耗资源较少且性能较高。

由于上述的问题,绝大多数的运维团队都会选择关闭该特性来避免执行异常,京东商城也出现过类似案例,严重影响业务正常运行。

最近系统中发现SQL执行异常,SQL类似为:

SELECT *

FROM tb_xxxx_xxxx

WHERE yn=0

AND C1=‘123456789’

OR C2=‘123456789’;

表上C1和C2列分别建有索引,但OR条件导致仅扫描任何一个索引都无法得到满足条件的全部数据,需要同时扫描两个索引并对两个临时结果求并集,但由于我们关闭了Index merge特性,导致执行优化器只能对表进行全表扫描并导致执行性能不佳。

该问题的临时解决办法为开启Index merge特性,但存在未知风险,因此我们建议修改SQL,将OR操作修改为UNION操作,使得不开启Index merge特性的情况下语句依然能使用多个索引,优化SQL为:

SELECT *

FROM tb_xxxx_xxxx

WHERE yn=0

AND C1=‘123456789’

UNION ALL

SELECT *

FROM tb_xxxx_xxxx

WHERE yn=0

AND C2=‘123456789’

AND C1<>‘123456789’

PS:

1、在第二个SELECT语句中增加第一个SELECT语句条件的反操作,从而保证两个SELECT 语句中没有重复数据,可以使用UNION ALL来求交集,避免UNION所带来的排序消耗。

2、在编写SQL语句时,需要注意OR条件的书写,

原SQL为:

WHERE yn=0

AND C1=‘123456789’

OR C2=‘123456789’

等价于:

WHERE (yn=0 AND C1=‘123456789’)

OR C2=‘123456789’

而实际需求要求所有返回数据满足yn=0的条件,应正确写为:

WHERE yn=0

AND (C1=‘123456789’

OR C2=‘123456789’)

MySQL中关于OR条件的优化的更多相关文章

  1. MySQL中的SQL的常见优化策略

    MySQL中的SQL的常见优化策略 MySQL中的索引优化 MySQL中的索引简介 1 避免全表扫描对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索 ...

  2. mysql中的SQL_CACHE(性能更优化)

    mysql中的sql_cache是个容易忽视的地方,要 使用的话,必须先设置query_cache_size, 以及设置query_cache_type ,其中 query_cache_type 这个 ...

  3. 在MySQL中如何使用覆盖索引优化limit分页查询

    背景 今年3月份时候,线上发生一次大事故.公司主要后端服务器发生宕机,所有接口超时.宕机半小时后,又自动恢复正常.但是过了2小时,又再次发生宕机. 通过接口日志,发现MySQL数据库无法响应服务器.在 ...

  4. MySQL中Index Condition Pushdown(ICP)优化

    在MySQL 5.6开始支持的一种根据索引进行查询的优化方式.之前的MySQL数据库版本不支持ICP,当进行索引查询是,首先根据索引来查找记录,然后在根据WHERE条件来过滤记录.在支持ICP后,My ...

  5. MySql中的有条件插入 insert where

    假设现在我们有这样的需求:当数据库中不存在满足条件的记录时,可以插入一条记录,否则程序退出.该怎么实现? 1年以上工作经验的人应该都能立即想到:去检查一下库里有没有记录,没有就插入,有就结束. int ...

  6. mysql中的if条件语句用法

    · IF(expr1,expr2,expr3) 如果 expr1 是TRUE (expr1 <> 0 and expr1 <> NULL),则 IF()的返回值为expr2;  ...

  7. Mysql中谓词使用date_format的优化

    优化前: SELECT a.* FROM t1 a, (SELECT obj_id,MAX(PRE_DETAIL_INST_ID) PRE_DETAIL_INST_ID FROM t1 WHERE D ...

  8. MySQL中怎么将LIMIT分页优化?

     1.语法:       *** limit [offset,] rows       一般是用于select语句中用以从结果集中拿出特定的一部分数据.       offset是偏移量,表示我们现在 ...

  9. MySQL中的索引优化

    MySQL中的SQL的常见优化策略 MySQL中的索引优化 MySQL中的索引简介 过多的使用索引将会造成滥用.因此索引也会有它的缺点.虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行 ...

随机推荐

  1. Android抖动的EditText

    Java代码:启动动画 Animation shake = AnimationUtils.loadAnimation(this, R.anim.shake); findViewById(R.id.pw ...

  2. 一种较为隐蔽ConcurrentModificationException情形

    ConcurrentModificationException是遍历过程中修改list而抛出的错误.就像前面分析的,单线程时这种错误主要是因为使用forEach造成:遍历一个拷贝,修改原始list,造 ...

  3. 81.内存模式实现cgi查询

    创建全局的二级指针 char ** g_pp;//全局的二级指针 获取数据有多少行 //获取行数 int getimax() { ; FILE *pf = fopen(path, "r&qu ...

  4. Weblogic问题汇总

    1. weblogic unable to get file lock问题 在项目使用过程中,非正常结束Weblogic进程导致Weblogic无法启动,出现以下错误: <BEA-141281& ...

  5. Vue自定义组件

  6. 【CS Round #43 E】Coprime Pairs

    [链接]点击打开链接 [题意] 让你选择n个数字,组成一个数组,使得这n个数字中恰好有k对,它们是互质的. [题解] 我们可以先找出前n个质数,那么接下来的问题就转化为,凑出rest = n*(n-1 ...

  7. JPA学习笔记(11)——使用二级缓存

    一级缓存 查询两次id为1的user User user1 = entityManager.find(User.class, 1); User user2 = entityManager.find(U ...

  8. vue的使用(一)

    之前找了一个学前端的同学,给我免费做几个页面,但是后来也就杳无音信了,今天脑子发热自己学一下vue算了. 本节目标:      安装以及数据绑定 1.安装和运行 ·必须要安装nodejs,这个到网上写 ...

  9. java三大特性:封装、继承、多态

    Java三大特性之封装   一.定义 封装性指的是将对象的状态信息隐藏在对象内部,不允许外部程序直接访问对象内部的信息,而是通过该类所提供的方法来实现对内部信息的操作和访问. 二.使用封装的好处: 1 ...

  10. hdu 5375 Gray code dp

    #include<stdio.h> #include<string.h> #include<algorithm> using namespace std; cons ...