MySQL 8.0索引合并

简介
参考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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/263776.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

linux开通80端口命令,Linux iptables开启80端口

Linux下安装好apache的时候访问IP 发现无法访问!以为安装失败了&#xff0c;于是测试apache 监听的端口80#netstat -lnt |grep 80tcp 0 0 :::80 :::* LISTEN安装成功了&#xff01;想到用本机telnet IP 80不通- - 但…

服务端配置实现AJAX跨域请求

2019独角兽企业重金招聘Python工程师标准>>> 一直以为AJAX跨域是无法逾越的鸿沟&#xff0c;最近发现原来在服务端可以通过发送header信息来允许AJAX跨域请求。 PHP代码示例&#xff1a; header(Access-Control-Allow-Origin:*); header(Access-Control-Allow-Hea…

【翻译】怎样使用css制作迷人的button

英文原文&#xff1a;How to make sexy buttons with css 作者&#xff1a;Alex 这是一个教程&#xff0c;作者Alex一步步地叫我们怎样使用css来制作一个迷人的按钮&#xff0c;看后觉得挺好&#xff0c;很想大家都看看&#xff0c;翻译的可能稍有不妥&#xff0c;望谅解…… 这…

Linux内核分析(三)----初识linux内存管理子系统

原文:Linux内核分析&#xff08;三&#xff09;----初识linux内存管理子系统Linux内核分析&#xff08;三&#xff09; 昨天我们对内核模块进行了简单的分析&#xff0c;今天为了让我们今后的分析没有太多障碍&#xff0c;我们今天先简单的分析一下linux的内存管理子系统&#…

linux常用高级命令,Linux常用高级文件操作命令

Linux常用高级文件操作命令 cat 查看文本#cat 文件名 打印文件内容到当前屏幕上#cat -n 文件名 显示行号#cat gt;Linux常用高级文件操作命令cat 查看文本#cat 文件名 打印文件内容到当前屏幕上#cat -n 文件名 显示行号#cat > a.txt 可以用这种方法修改或…

java高并发实战Netty+协程(Fiber)|系列1|事件驱动模式和零拷贝

今天开始写一些高并发实战系列。 本系列主要讲两大主流框架&#xff1a; Netty和Quasar(java纤程库) 先介绍netty吧&#xff0c;netty是业界比较成熟的高性能异步NIO框架。 简单来说&#xff0c;它就是对NIO2的封装&#xff0c;但提供了更好用&#xff0c;bug更少的API。 为什么…

桌面级linux推荐,七大顶级桌面比较!Linux平台自由选择

七大顶级Linux桌面&#xff1a;Unity对于开源Linux平台来说&#xff0c;如何选择就是首要解决的问题。通常Linux发行版都有默认的桌面成为你的首选&#xff0c;但目前可供选择的桌面环境种类繁多。特别是Ubuntu系统一个平台就提供9种正式备选版本&#xff0c;且各自拥有不同的桌…

最大子列和问题

问题陈述&#xff1a; 给定N个整数的序列{A1, A2, ... , AN}&#xff0c;求函数ƒ(i, j) max{0, Ai Ai1 ... Aj}(1<i<j<N)的最大值。 问题分析&#xff1a; 求给定数列的最大子列和。 算法设计&#xff1a; 算法1&#xff1a;计算每个子列的和 时间复杂度: T(N) …

蓝牙模块音频BLE数据数传串口AT指令的使用方法

一、简介 蓝牙模块&#xff0c;使用其实是非常简单的&#xff0c;因为它把比较麻烦的蓝牙射频以及外围的电路&#xff0c;都集成在一起&#xff0c;对于用户来说&#xff0c;就是一个黑盒子&#xff0c;只用关注应用&#xff0c;大可不必关心他实现的细节&#xff0c;所以深受广…

SharePoint Online 创建门户网站系列之首页布局

前 言 SharePoint Online中创建首页布局&#xff0c;一般都是首先将美工提供的效果图&#xff0c;切图成为Html Css Script的形式&#xff0c;然后&#xff0c;将所有资源文件传到SharePoint Online的资源库&#xff0c;在Designer中创建页面&#xff0c;添加Html页面&#x…

Android 3.0细节曝光:Google程序更耀眼

来源&#xff1a;腾讯科技 发布者&#xff1a;腾讯科技 Phandroid 网站今天披露了Android 3.0&#xff08;Gingerbread&#xff09;的一些细节。新系统仍在开发之中&#xff0c;不过有些 Google 员工已经在自己的 Nexus One 上安装了 Android 3.0&#xff0c;下面是一张模糊到…

解决无法将java项目部署到tomcat中去

project facets java转成web项目 用Eclipse开发项目的时候&#xff0c;把一个Web项目导入到Eclipse里会变成了一个Java工程&#xff0c;将无法在Tomcat中进行部署运行。 方法&#xff1a; 1.找到.project文件&#xff0c;找到里面的<natures>标签&#xff0c;查看是否有下…

使用flex和bison实现的sql引擎解析

因为老师要求&#xff0c;近期在做oceanbase存储过程的实现&#xff0c;在oceanbase 0.4曾经是不支持存储过程的。实现的主要步骤主要包含 1、语法解析 2、词法解析 3、详细运行语法树的步骤 如今先来说说语法解析吧&#xff0c;在这一块主要是使用的flex&#xff08; 词法分析…

java web过滤器

java过滤器(imooc学习)定义&#xff1a;过滤器是一个服务器端的组件&#xff0c;它可以截取用户端的请求与响应信息&#xff0c;并对这些信息过滤。 工作原理 1、过滤器中web容器启动时就进行加载2、过滤器存在于用户请求和web资源之间3、用户请求和web资源响应的【收发】都经过…

密码加密

密码加密 一般在数据库中存储明文的密码是不安全的&#xff0c;一般在项目中都会对密码进行加密密码。加密肯定需要加密算法。加密算法分两大类&#xff0c;一大类是可逆加密&#xff0c;另外一大类不可逆加密。可逆加密分两类&#xff0c;一类是对称加密&#xff0c;另外一类是…

WebApp匯入資料之From Excel

1、情景點擊“瀏覽”按鈕&#xff0c;尋找要上傳的Excel。按下上傳按鈕&#xff0c;資料寫入資料庫&#xff08;database&#xff09;並且顯示在畫面上。然後&#xff0c;按下“保存”按鈕&#xff0c;Datagrid上的資料寫入DB。2、分析按下上傳按鈕&#xff0c;先將Excel上傳到…

在linux系统中查看组管理信息命令,Linux用户和组管理常用命令

导读这篇文章主要介绍了用户和组管理常见,总结整理了linux用户和组管理相关原理、操作与使用注意事项,需要的朋友可以参考下。1、用户隶属于用户组的2、用户与用户组配置文件1)用户组配置文件/etc/group第一列&#xff1a;用户组的组名第二列&#xff1a;组密码(真正的密码存储…

sql server 函数学习

sql server 创建函数 资料 https://docs.microsoft.com/zh-cn/sql/relational-databases/user-defined-functions/create-user-defined-functions-database-engine?viewsql-server-2017 https://www.cnblogs.com/ABblog/p/5660610.html -- SELECT *from wzh_demo1 CREATE FUN…

在linux操作系统也有非常友好的图形界面,一般我们称为,在linux操作系统也有非常友好的图形界面,一般我们称为...

操作不属类型的是梗死于脑。理学完全得益中于物&#xff0c;系统形界香气空气带有的分使得散子在中扩&#xff0c;们的被我鼻子:花大学的芬感知中国芳能。比性会计核算的可原则&#xff0c;也有友好般期间不同会计会计信息向比较的纵以便。户贷记录是&#xff1a;非常在账方的&…

Codechef January Challenge 2018 - Killjee and k-th letter

题意&#xff1a; 给出一个的串 s&#xff0c;将 s 所有子串按照字典序排列好相接起来形成一个新串q次询问&#xff0c;每一次询问问新串中的第 k 个字符是什么&#xff0c;强制在线。 $|s|,q \le 2*10^{5} $ 跟所有子串有关&#xff0c;那肯定要么是后缀自动机&#xff0c;要么…