索引策略-多列索引

一. 前言

当我们对多列索引的理解不够深刻的时候,往往会为每个列创建独立的索引或者按照错误的顺序创建多列索引。

二. 案例说明

问题一: 为每个列创建独立索引

CREATE TABLE t(c1 INT,c2 INT,c3 INT,KEY(c1),KEY(c2),KEY(c3)
);

这种索引策略,一般都是由于人们听到一些专家诸如"把Where条件里面的列都建上索引"这样模糊的建议导致的。这样一来最好也只能是"一星"索引,其性能比真正最优的索引可能差几个数量级。有时如果无法设计一个"三星"索引,那么不如忽略掉Where子句,集中精力优化索引顺序,或者创建一个全覆盖索引

2.1 三星索引

一星: 索引将相关的记录放在一起
二星: 如果索引中的数据顺序查找顺序一致
三星: 如果索引中的列包含了查询中需要的全部列
在这里插入图片描述

三星索引的相关实践可以参考: 三星索引实战

2.2 Mysql底层对单列索引的处理

在多个列上建立独立的单列索引大部分情况下并不能提高Mysql的查询性能。Mysql 5.0 和更新版本引入了一种叫"索引合并"(index merge)的策略,一定程度上可以使用表上的多个单列索引来定位指定的行。更早版本的 Mysql只能使用其中某一个单列索引,然而这种情况下没有哪一个独立的单独索引是非常有效的。例如,下表 film_actor在字段 film_id 和 actor_id 各有一个单列索引。但对于下面这个查询的 Where 条件,这两个单列索引都不是好的选择:

建表语句:

CREATE TABLE `film_actor` (`id` int(20) NOT NULL AUTO_INCREMENT COMMENT '主键id',`actor_id` int(20) NOT NULL COMMENT '演员id',`film_id` int(20) DEFAULT NULL COMMENT '电影id',PRIMARY KEY (`id`) USING BTREE,KEY `idx_film_id` (`film_id`) USING BTREE,KEY `idx_actor_id` (`actor_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4

查询语句:

SELECT film_id, actor_id FROM film_actor
WHERE actor_id = 1 OR film_id = 1;

执行计划:
在这里插入图片描述

在老的 Mysql版本中,Mysql对这个查询会使用全表扫描。除非改下成如下的两个查询UNION的方式:

SELECT film_id, actor_id FROM film_actor WHERE actor_id = 1
UNION ALL
SELECT film_id, actor_id FROM film_actor WHERE film_id = 1
AND actor_id <> 1

执行计划:
在这里插入图片描述

但在Mysql 5.0和更新的版本中,查询能够同时使用两个单列索引进行扫描,并将结果进行合并。这种算法有三个变种: OR条件的联合(union),AND条件的相交(intersection),组合前两种情况的联合及相交。

Tips: 索引合并通过能在执行计划的 Extra上看到

在这里插入图片描述

2.3 索引合并背后的问题

索引合并策略有时候是一种优化的结果,但实际上更多的时候说明表的索引建的很糟糕。

  • 当出现服务器对多个索引做相交操作时(通常有多个AND条件),通常意味着需要一个包含所有相关列的多列索引,而不是多个独立的单列索引。
  • 当服务器需要对多个索引做联合操作时(通常有多个OR条件),通常需要消耗大量CPU内存资源在算法的缓存,排序和合并操作上。特别是当中有些索引选择性不高,需要合并扫描返回大量数据的时候。
  • 更重要的是,优化器不会把这些计算到"查询成本"(cost) 中,优化器只关心随机页面读取。这会使得查询的成本被"低估",导致该执行计划还不如直接走全表扫描。这样做不但会消耗更多的CPU和内存资源,还可能会影响查询的并发性,但如果是单独运行这样的查询则往往会忽略对并发性的影响。通常来说,还不如像在Mysql 4.1 或者更早的时代一样,将查询改写成 UNION的方式往往更好。

如果在EXPLAIN中看到索引合并,应该好好检查一下查询和表的结构,看是不是已经是最优的。也可以通过参数 optimizer_switch 来关闭索引合并功能,也可以使用 Ignore index 提示让优化器忽略掉某些索引

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

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

相关文章

[足式机器人]Part2 Dr. CAN学习笔记-Advanced控制理论 Ch04-8 状态观测器设计 Linear Observer Design

本文仅供学习使用 本文参考&#xff1a; B站&#xff1a;DR_CAN Dr. CAN学习笔记-Advanced控制理论 Ch04-8 状态观测器设计 Linear Observer Design

LangChain 74 有用的或者有害的helpful or harmful Scoring Evaluator

LangChain系列文章 LangChain 60 深入理解LangChain 表达式语言23 multiple chains链透传参数 LangChain Expression Language (LCEL)LangChain 61 深入理解LangChain 表达式语言24 multiple chains链透传参数 LangChain Expression Language (LCEL)LangChain 62 深入理解Lang…

thinkphp递归实现无限级子分类合并上级children

//设别分类列表public function getCategoryList(){$list = Db::name(categorys)->select(

S1-06 消息队列

消息队列 消息队列是一种在多任务操作系统中广泛使用的通信机制。它可以用于不同任务之间的消息传递&#xff0c;从而实现数据共享和协调处理任务之间的顺序。 消息队列通常具有以下基本特点&#xff1a; 消息队列的大小有限&#xff1a;消息队列被设计为一种缓冲区&#xff…

Vulnhub靶机:driftingblues 1

一、介绍 运行环境&#xff1a;Virtualbox 攻击机&#xff1a;kali&#xff08;10.0.2.15&#xff09; 靶机&#xff1a;driftingblues1&#xff08;10.0.2.17&#xff09; 目标&#xff1a;获取靶机root权限和flag 靶机下载地址&#xff1a;https://www.vulnhub.com/entr…

性能测试分析案例-使用动态追踪定位性能瓶颈

所谓动态追踪&#xff0c;就是在系统或者应用程序正常运行的时候&#xff0c;通过内核中提供的探针&#xff0c;来动态追踪它们的行为&#xff0c;从而辅助排查出性能问题的瓶颈。 使用动态追踪&#xff0c;可以在不修改代码、不重启服务的情况下&#xff0c;动态了解应用程序或…

记录汇川:H5U与Fctory IO测试11

主程序&#xff1a; 子程序&#xff1a; IO映射 子程序&#xff1a; 出料程序 子程序&#xff1a; 自动程序 Factory IO配置&#xff1a; 实际动作如下&#xff1a; Fctory IO测试11

vue前端开发自学,组件的生命周期函数介绍001

vue前端开发自学,组件的生命周期函数介绍001&#xff01;今天介绍一下&#xff0c;组件自身的生命周期函数。又叫做&#xff0c;钩子函数。可以借助于这些钩子函数&#xff0c;实现很多我们预想的效果。比如&#xff0c;在组件渲染 之前&#xff0c;就做一些特殊的操作等等。 …

流量加密之OpenSSL反弹加密

目录 1、OpenSSL 简介 2、使用 OpenSSL 反弹加密 shell 3、使用wireshark抓包验证 4、搭建 HTTPS Server 1、OpenSSL 简介 OpenSSL 是一个强大的、商业级的、功能齐全的开源工具包&#xff0c;用于 TLS&#xff08;以前称为 SSL&#xff09;、DTLS 和 QUIC&#xff08;目前…

What does `HandlerInterceptor` do?

HandlerInterceptor 是 SpringMVC 中的一个接口&#xff0c;在SpringMVC应用中它提供了一种实现应用级拦截器的机制。 第1步&#xff1a;引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web<…

实现JavaScript的函数链式执行

本篇文章将会实现函数链式执行&#xff0c;链式步骤延时等操作。 1.工具类 const executor (name) > {/*** 执行器名称*/const executorName name;/*** 方法数组*/const methodArray [];/*** 同步执行某个方法*/function run(func){methodArray.push(func);return this…

反敏捷宣言

很多时候&#xff0c;敏捷在实践中并没有帮助团队更好的完成工作&#xff0c;而是成为了某种障碍以及僵化的流程。原文: The Anti-Agile Manifesto 警告1: 如果你是敏捷教练或Scrum Master或任何其他形式的敏捷支持者&#xff0c;本文的很多内容都会让你不爽。本文的目的之一是…