合适的索引顺序

一.前言

正确的顺序依赖于使用索引的查询,并且同时需要考虑如何更好地满足排序分组的需要。因为哈希或者其他类型的索引并不会像 B-Tree索引一样顺序存储数据,所以这里只针对B-Tree展开讨论。

二.合适的索引顺序

1. 概念

对于如何选择索引顺序有一个经验法则: 将选择性最高的列放在索引最前列。当不需要考虑排序分组时,将选择性最高的列放在前面通常是很好的,这时索引的作用只是用于优化 Where 条件的查找。在这种情况下,这样设计的索引确实能够最快地过滤出需要的行,对于在Where子句中只使用了索引前缀列的查询来说性能也更高。然而,性能不只是依赖于索引索引列的选择性(整体基数),也和查询条件的具体值有关,也就是和值分布有关。

2. 案例

下面有个查询:

SELECT * FROM payment WHERE staff_id = 2 AND customer_id = 584;

那按照平时的最左前缀原则,我们是不是建一个(staff_id,customer_id)的索引合适呢?

其实不然,我们可以跑一些查询来确定在这个表中值的分布情况,并确定哪个列的选择性更高。

2.1. 查看Where条件分支对应的基数有多大
SELECT SUM(staff_id=2),SUM(customer_id=584) FROM payment;

在这里插入图片描述

根据前面的经验法则,应该将所有列customer_id 放在前面,因为对应条件值的 customer_id数量更小。我们在来看看对于这个customer_id 的条件值,对应的staff_id 列的选择性如何:

SELECT SUM(staff_id=2) FROM payment WHERE customer_id=584

在这里插入图片描述
这样做有一个地方需要注意,查询的结果非常依赖于选定的具体值。如果按上述方法优化,可能对其他一些条件值的查询不公平,服务器的整体性可能变得更糟,或者其他某些查询的运行变得不如预期。

2.2. 按照全局基数和选择性

如果是从诸如 pt-query-digest这样的工具的报告中提取"最差"查询,那么再按上述方法选定的索引顺序往往是非常高效的。如果没有类似具体的查询类运行,那么最好还是按经验法则来做,因为经验法则考虑的是全局基数和选择性

SELECT COUNT(DISTINCT staff_id)/COUNT(*) AS staff_id_selectivity,
COUNT(DISTINCT customer_id)/COUNT(*) AS customer_id_selectivity,COUNT(*) FROM payment;

在这里插入图片描述

从上面的结果也可以看出 customer_id 的选择性更高,所以答案是将其作为索引列的第一列:

ALTER TABLE payment ADD KEY(customer_id, staff_id);

3. 选择性不高的索引列

当使用前缀索引的时候,在某些条件值的基数比正常值高的时候,问题就来了。例如,在某些应用程序中,对于没有登录的用户,都将其用户名记录为"guest",在记录用户行为的会话(session)表和其他记录用户活动的表中"guset"就成为一个特殊的ID。一旦涉及到这个查询,可能性能就会大不相同。

下面给出一个真实案例,在一个用户分享购买商品和购买经验的论坛上,这个特殊表上的查询运行得非常慢:

SELECT COUNT(DISTINCT threadId) AS COUNT_VALUE FROM Message
WHERE (groupId=10137) AND (userId=1288826) AND (anoymous=0)
ORDER BY priority DESC, modifiedDate DESC

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

看上去已经建立了索引(groupId,userId),如果不考虑列的基数,这看起来是一个非常合理的选择,但如果考虑一下userId 和groupId条件匹配的行数,可能会有不同的想法了:

SELECT COUNT(*), SUM(groupId=10137),SUM(userId=1288826),
SUM(anoymous=0) FROM Message

在这里插入图片描述
从上面的结果可以看出符合组(groupId)条件几乎满足表中的所有行,符合用户(userId)条件有130万条记录——也就是说索引基本上没什么作用。这里从索引层面上已经解决不了问题,我们可以从业务上区分这类特殊用户和组,禁止针对这类用户和组执行这个查询。

三.总结

  • 从上面的案例可以看到经验法则和推论在多数情况下是有用的,但注意不要假设平均情况下的性能也能代表特殊情况下的性能,特殊情况可能会摧毁整个应用的性能。
  • 最后,尽管关于选择性技术的经验法则值得去研究和分析,但Where子句中的排序,分组范围条件等其他因素对查询的性能也会造成非常大的影响。

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

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

相关文章

Java医院信息管理系统

技术框架: springboot shiro layui jquery thymeleaf nginx 有需要的可以联系我。 运行环境: jdk8 mysql IntelliJ IDEA maven项目功能: 本项目是用springbootlayuishiro写的医院管理系统,系统的业务比较复杂&#x…

机器学习周刊第五期:一个离谱的数据可视化Python库、可交互式动画学概率统计、机器学习最全文档、快速部署机器学习应用的开源项目、Redis 之父的最新文章

date: 2024/01/08 这个网站用可视化的方式讲解概率和统计基础知识,很多内容还是可交互的,非常生动形象。 大家好,欢迎收看第五期机器学习周刊 本期介绍7个内容,涉及Python、概率统计、机器学习、大模型等,目录如下: 一个离谱的Python库看见概率,看见统计2024机器学习最…

BGP最通俗易懂的讲解——路由反射器

路由反射器 点赞关注,持续更新 路由反射器RR (Route Reflector) : 允许把从IBGP 对等体学到的路由反射到其他BGP对等体的BGP设备。客户机 (Client) : 与RR形成反射邻居关系的IBGP设备。在AS内部客户机只需要与RR建立邻居关系。非客户机 (Non-Client) …

【linux】Debian10.0配置vsftpd

一、基本步骤 在 Debian 10 (Buster) 上要配置 vsftpd (Very Secure FTP Daemon),请按照以下步骤操作: 1. 安装 vsftpd: sudo apt update sudo apt install vsftpd 2. 在启动配置之前,建议备份原始的配置文件: sudo cp /etc/vsftpd.con…

论文阅读 Vision Transformer - VIT

文章目录 1 摘要1.1 核心 2 模型架构2.1 概览2.2 对应CV的特定修改和相关理解 3 代码4 总结 1 摘要 1.1 核心 通过将图像切成patch线形层编码成token特征编码的方法,用transformer的encoder来做图像分类 2 模型架构 2.1 概览 2.2 对应CV的特定修改和相关理解 解…

【算法Hot100系列】跳跃游戏

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学习,不断总结,共同进步,活到老学到老导航 檀越剑指大厂系列:全面总结 jav…

为什么说在java中万物皆方法?

为什么说在java中万物皆方法? 在开始前我有一些资料,是我根据网友给的问题精心整理了一份「java的资料从专业入门到高级教程」, 点个关注在评论区回复“888”之后私信回复“888”,全部无偿共享给大家!!&am…

SwitchyOmega插件管理海外動態IP代理設置教程

SwitchyOmega插件很好解決了管理多個代理並在它們之間切換的問題,通過本文來全面瞭解SwitchyOmega,比如SwitchyOmega插件的用途、它的主要功能和應用、怎麼下載和使用,如何管理海外動態IP代理。 SwitchyOmega插件有什麼用途? Swit…

关于Windows 10的操作中心 ,看这篇文章就可以了

这篇文章介绍了Windows 10操作中心,也称为通知中心,以及如何使用它。操作中心会在需要你注意的事情时发送警报。 如何在操作中心中访问和解决通知 Windows操作中心显示为Windows任务栏右下角的发言气泡。图标下的数字表示你有未解析的通知。 通知会在…

取代房子,中国又一种资本在崛起(深度)

我一直有一个观点:经济形势好的时候,只要不是夕阳行业,做什么都能过得不错。经济形势差的时候,对于个人来说,拼的就是学习能力。 10年前,在市场上很吃香的是MBA,那时候企业需要高速发展&#x…

maven多个module打包

common是父组件,servicebase依赖于commonutils,如下图 1.打servicebase包时出现问题:找不到commonutils的jar包,但是commonutils包可以正常打,并且可以install到本地maven仓库。 解决方式: servicebase 的…

JAVA正则表达式第二个作用:爬取

目录 本地数据爬取: 本地爬取练习: 网络爬取: ----- 以下为均本地数据爬取: 带条件爬取 贪婪爬取和非贪婪爬取: 例题 1:使获取 1 为不贪婪 *例题 2:使获取 0、1 都为不贪婪 之前介绍了正…