简介
参考https://dev.mysql.com/doc/refman/8.0/en/index-merge-optimization.html#index-merge-intersection。
索引合并是通过多个range类型的扫描并且合并它们的结果集来检索行的。仅合并来自单个表的索引扫描,而不是跨多个表的索引扫描。合并会产生底层扫描的三种形式:unions(合并)、intersections(交集)、unions-of-intersections(先取交集再合并)。
以下四个例子会产生索引合并:
1、SELECT * FROM tbl_name WHERE key1 = 10 OR key2 = 20;
2、SELECT * FROM tbl_name WHERE (key1 = 10 OR key2 = 20) AND non_key = 30;
3、SELECT * FROM t1, t2 WHERE (t1.key1 IN (1,2) OR t1.key2 LIKE 'value%') AND t2.key1 = t1.some_col;
4、SELECT * FROM t1, t2 WHERE t1.key1 = 1 AND (t2.key1 = t1.some_col OR t2.key2 = t1.some_col2);
索引合并有以下已知的局限性:
1、如果查询语句包含一个带有严重AND/OR嵌套的复杂的WHERE子句而MySQL没有选择最佳计划,那么可以尝试使用以下的标志符转换:
(x AND y) OR z => (x OR z) AND (y OR z)
(x OR y) AND z => (x AND z) OR (y AND z)
2、索引合并不适用于全文索引。
在 EXPLAIN 语句输出的信息中,索引合并在type列中表现为“index_merge”,在这种情况下,key列包含使用的索引列表。
索引合并访问方法有几种算法,表现在 EXPLAIN 语句输出的Extra字段中:
Using intersect(...)
Using union(...)
Using sort_union(...)
下面将更详细地描述这些算法。优化器根据各种可用选项的成本估计,在不同的索引合并算法和其他访问方法之间进行选择。
Index Merge Intersection算法
Index Merge Intersection算法对所有使用的索引执行同步扫描,并生成从合并的索引扫描接收到的行序列的交集。
这种算法适用于当WHERE子句被转换成多个使用AND连接的不同索引key上的范围条件,且条件是以下两种之一:
一、这种形式的N部分表达式,索引正好包括N个字段(所有索引字段都被覆盖),N>=1,N如果大于1就是复合索引:
key_part1 = const1 AND key_part2 = const2 ... AND key_partN = constN。
二、InnoDB表主键上的任何范围条件。
例子:
1.SELECT * FROM innodb_table
WHERE primary_key < 10 AND key_col1 = 20;
2.SELECT * FROM tbl_name
WHERE key1_part1 = 1 AND key1_part2 = 2 AND key2 = 2;
Index Merge Union算法
该算法类似于Index Merge Intersection算法,适用于当WHERE子句被转换成多个使用OR连接的不同索引key上的范围条件,且条件是以下三种之一:
一、这种形式的N部分表达式,索引正好包括N个字段(所有索引字段都被覆盖),N>=1,N如果大于1就是复合索引:
key_part1 = const1 AND key_part2 = const2 ... AND key_partN = constN。
二、InnoDB表主键上的任何范围条件。
三、符合Index Merge Intersection算法的条件。
例子:
1.SELECT * FROM t1
WHERE key1 = 1 OR key2 = 2 OR key3 = 3;
2.SELECT * FROM innodb_table
WHERE (key1 = 1 AND key2 = 2)
OR (key3 = 'foo' AND key4 = 'bar') AND key5 = 5;
Index Merge Sort-Union算法
该算法适用于当WHERE子句被转换成多个使用OR连接的不同索引key上的范围条件,但是不符合 Index Merge Union算法的。Index Merge Sort-Union和Index Merge Union算法的区别在于,Index Merge Sort-Union必须首先获取所有行的行id并在返回任何行之前对它们进行排序。
例子:
1.SELECT * FROM tbl_name
WHERE key_col1 < 10 OR key_col2 < 20;
2.SELECT * FROM tbl_name
WHERE (key_col1 > 10 OR key_col2 = 20) AND nonkey_col = 30;
索引合并引发的死锁
索引合并是MySQL优化查询速度的一种方式,但是错误的使用也会导致死锁,处理方式就是将引起索引合并的索引修改为复合索引。曾经就遇到过和以下所讲的几乎一样的问题,所以这里就直接把别人写的转载过来,转载自:https://blog.csdn.net/hehehaha1123/article/details/59058067。
=============================================================================
概述
前几天排查了一个死锁问题,最开始百思不得其解,因为发生死锁的两个事务是单语句事务,语句类型相同(where属性列相同,仅值不同),而且语句都走了相同的索引,但最终确实发生了死锁。通过定位排查发现,问题的源头就是index_merge,死锁的原因也很普通,两个事务加锁顺序不同,并存在相互等待的情况。因为这个案例比较特殊,所以在此分享给大家。
死锁信息
拿到死锁问题,首先需要查看几个基本信息,包括死锁等待关系,表结构定义等。
1.表结构定义
Create Table: CREATE TABLE `t_xxx_customer` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`partner_id` bigint(20) unsigned DEFAULT NULL,
`customer_id` bigint(20) unsigned DEFAULT NULL,
`deleted` tinyint(4) DEFAULT NULL,
`partner_user_id` bigint(20) unsigned DEFAULT NULL,
`xxx_id` varchar(128) DEFAULT NULL,
`xxx_name` varchar(256) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `partner_id` (`partner_id`),
KEY `customer_id` (`customer_id`),
KEY `partner_user_id` (`partner_user_id`)
) ENGINE=InnoDB AUTO_INCREMENT=140249 DEFAULT CHARSET=utf8;
2.死锁信息提取与分析
通过show engine innodb status;命令可以获取innodb引擎中最近一次发生死锁的信息,信息如下:
*** (1) TRANSACTION: UPDATE t_xxx_customer SET xxx_id='101', xxx_name='bbb' where customer_id=235646 and partner_id=1688 and deleted=0;
*** (1) HOLDS THE LOCK(S): RECORD LOCKS space id 1640 page no 3947 n bits 432 index partner_id of table xxx.t_xxx_customer trx id 2625291980 lock_mode X locks rec but not gap Record lock, heap no 334 PHYSICAL RECORD: n_fields 2; compact format; info bits 0 0: len 8; hex 0000000000000698; asc ;; 1: len 8; hex 0000000000021747; asc G;;
*** (1) WAITING FOR THIS LOCK TO BE GRANTED: RECORD LOCKS space id 1640 page no 3395 n bits 160 index PRIMARY of table t_xxx_customer trx id 2625291980 lock_mode X locks rec but not gap waiting Record lock, heap no 89 PHYSICAL RECORD: n_fields 25; compact format; info bits 0
*** (2) TRANSACTION: UPDATE t_xxx_customer SET xxx_id='102', xxx_name='aaa' where customer_id=151069 and partner_id=1688 and deleted=0;
*** (2) HOLDS THE LOCK(S): RECORD LOCKS space id 1640 page no 3395 n bits 160 index PRIMARY of table xxx.t_xxx_customer trx id 2625291981 lock_mode X locks rec but not gap
*** (2) WAITING FOR THIS LOCK TO BE GRANTED: RECORD LOCKS space id 1640 page no 3947 n bits 432 index partner_id of table xxx.t_xxx_customer trx id 2625291981 lock_mode X locks rec but not gap waiting Record lock, heap no 334 PHYSICAL RECORD: n_fields 2; compact format; info bits 0 0: len 8; hex 0000000000000698; asc ;; 1: len 8; hex 0000000000021747; asc G;;
*** WE ROLL BACK TRANSACTION (2)
从死锁结果来看,我们很容易看到事务1持有 partner_id二级索引上的锁,等待PK索引上的锁;而事务2持有PK索引锁,等待partner_id二级索引上的锁,两个事务相互持有对方需要的锁资源,而无法往前推进,造成死锁。单从死锁信息来看,我们可能会比较疑惑,每个事务只有一个语句,为什么同样的语句,对二级索引和主键的加锁顺序会不同?
产生死锁的原因
首先我们来看看语句的执行计划,
语句的type是index_merge,Extra的信息是Using intersect(customerid,partnerid),从而我们得知语句执行计划走了index_merge优化,单个语句通过两个索引(customerid,partnerid)来提取记录集合并取交集获得最终结果集。index_merge具体算法不在此展开,基本使用场景是语句包含多个查询条件,每个条件都单独存在索引,而单个条件的索引过滤度不高,组合起来过滤度比较高,这个时候就可能会走index_merge优化,使得单个SQL语句可以同时利用两个索引过滤。会不会与index_merge有关呢?
在index_merge的情况下,会导致二级索引与主键索引顺序不一致的情况吗?结合上面的死锁信息,我们得知死锁两个的二级索引key是0x698,而主键索引key是0x21747。我们看看到底是哪条记录的主键和二级索引发生了死锁,
可以看到0x21747对应的customer_id为151069,partner_id为1688,是不是感觉似曾相识,对的,第二个事务的语句查询条件就是这两个条件的组合。这说明,对于这条记录,第一个事务语句只有partnerid索引(1688)满足条件;对于第二个事务,customer_id和partner_id索引都满足条件。由于每个语句执行时都需要利用两个二级索引,假设先使用customer_id索引扫描,然后使用partner_id索引扫描,那么对于id为0x21747的记录,事务1的partner_id=1688满足条件,加partner_id锁,然后对对应的PK索引加锁;对于事务2,对customer_id= 151069加锁,对对应的PK索引加锁,然后对partner_id=1688索引加锁。那么对partner_id二级索引和PK主键索引在两个事务的上锁顺序是相反的,所以导致了死锁。对于id为0x21747记录:
序号
事务1
事务2
1
customer_id 不满足条件不加锁
customer_id= 151069 加锁
2
partner_id=1688加锁
PK=0x21747加锁
3
PK=0x21747加锁
partner_id=1688加锁
4
 
PK=0x21747加锁
表格第2步和第3步,两个事务的加锁顺序是相反的,导致了死锁发生。
=============================================================================

转载于:https://www.cnblogs.com/gjb724332682/p/11018678.html

MySQL 8.0索引合并相关推荐

  1. c语言 字符串 正序再倒序_新特性解读 | MySQL 8.0 索引特性3 -倒序索引

    原创作者:杨涛涛 我们今天来介绍下 MySQL 8.0 引入的新特性:倒序索引. MySQL长期以来对索引的建立只允许正向asc存储,就算建立了desc,也是忽略掉. 比如对于以下的查询,无法发挥索引 ...

  2. 千呼万唤始出来,MySQL 8.0索引三剑客之函数索引

    MySQL 8.0新特性专栏目录 <MySQL开发规范>过时了,视图查询性能提升了一万倍 你真的会用EXPLAIN么,SQL性能优化王者晋级之路 索引三剑客之降序索引和不可见索引 千呼万唤 ...

  3. mysql 8函数索引_新特性解读 | MySQL 8.0 索引特性1-函数索引

    原创作者:杨涛涛 函数索引顾名思义就是加给字段加了函数的索引,这里的函数也可以是表达式.所以也叫表达式索引. MySQL 5.7 推出了虚拟列的功能,MySQL8.0的函数索引内部其实也是依据虚拟列来 ...

  4. mysql force index报错_新特性解读 | MySQL 8.0 索引特性4-不可见索引

    MySQL 8.0 实现了索引的隐藏属性.当然这个特性很多商业数据库早就有了,比如ORACLE,在11g中就实现了.我来介绍下这个小特性. 介绍 INVISIBLE INDEX,不可见索引或者叫隐藏索 ...

  5. 中累计直方图_新特性解读 | MySQL 8.0 直方图

    原创作者:杨涛涛 MySQL 8.0 推出了histogram,也叫柱状图或者直方图.先来解释下什么叫直方图. 关于直方图 我们知道,在DB中,优化器负责将SQL转换为很多个不同的执行计划,完了从中选 ...

  6. 警惕参数变化,MySQL 8.0 升级避免再次踩坑

    MySQL 8.0新特性专栏目录 <MySQL开发规范>过时了,视图查询性能提升了一万倍 你真的会用EXPLAIN么,SQL性能优化王者晋级之路 索引三剑客之降序索引和不可见索引 千呼万唤 ...

  7. MySQL 优化之 index merge(索引合并)

    深入理解 index merge 是使用索引进行优化的重要基础之一.理解了 index merge 技术,我们才知道应该如何在表上建立索引. 1. 为什么会有index merge 我们的 where ...

  8. mysql+index组合索引_MySQL 优化之 index merge(索引合并)

    标签: MySQL5.0之前,一条语句中一个表只能使用一个索引,无法同时使用多个索引.但是从5.1开始,引入了 index merge 优化技术,对同一个表可以使用多个索引.理解了 index mer ...

  9. mysql 可以用多个索引_mysql索引合并:一条sql可以使用多个索引

    前言 mysql的索引合并并不是什么新特性.早在mysql5.0版本就已经实现.之所以还写这篇博文,是因为好多人还一直保留着一条sql语句只能使用一个索引的错误观念.本文会通过一些示例来说明如何使用索 ...

最新文章

  1. 【神经网络】(11) 轻量化网络MobileNetV1代码复现、解析,附Tensorflow完整代码
  2. Linux的shell脚本
  3. 熊猫烧香是天才作品吗?
  4. java 实现 常见排序算法(一) 冒泡排序
  5. android studio课程管理系统,8 个最优秀的 Android Studio 插件
  6. java中一直gc_如果JVM在执行GC时一直在移动对象,那么它如何解析引用?
  7. linux as5 启动mysql_RedHat AS5 PHP添加JSON模块
  8. 微型计算机断电后信息将会丢失,2011年计算机基础知识精选部分及答案三
  9. keil如何下载STM32芯片F1/F4固件库
  10. 构建Arduino和TFT LCD条形码扫描仪
  11. Sicily.1004. I Conduit!
  12. EXCEL表单元格内特定内容的提取
  13. [渝粤教育] 南京信息职业技术学院 模拟电子技术 参考 资料
  14. 对于程序员“中年危机”的一点思考
  15. TensorBoard对训练过程可视化(不用tf.summaries.merge_all)
  16. Oracle 查询库文件信息
  17. STM32开发 --- 1.8寸显示屏ST7735_输出英文、汉字、图片
  18. 普通人如何在网上能月入3000以上
  19. Stata数据处理:xtbalance-非平衡面板之转换
  20. git安装问题解决方案

热门文章

  1. IDEA下搜狗输入法输入中文时卡着不动的参考解决方法
  2. 了解javascript中函数执行顺序
  3. 微信小程序——操作数据库
  4. Spring 钩子之BeanFactoryPostProcessor和BeanPostProcessor
  5. 21 Fragment和短语法应用
  6. 阿里云ecs实例中创建数据库
  7. cisco 动态路由协议RIP笔记
  8. Ansible 五(inventory文件 主机清单)
  9. 算法复杂度为O(N) 的排序算法
  10. PMP - 2011年6月考前辅导班