MySQL之创建高性能的索引(十二)

创建高性能的索引

支持多种过滤条件

这些索引将满足大部分最常见的搜索查询,但是如何为一些生僻的搜索条件(比如has_pictures、eye_color、hair_colr和education)来设计索引呢?这些列的选择性搞,使用也不频繁,可以选择忽略它们,让MySQL多扫描一些额外的行即可。另一个可选的方法是在age列的前面加上这些列,在查询时使用前面提到过的IN()基数来处理搜索时没有指定这些列的场景。你可能已经注意到了,我们一直将age列放在索引的最后面。age列有什么特殊的地方吗?为什么要放在索引的最后?我们总是尽可能让MySQL使用更多的索引列,因为查询只能使用索引的最左前缀,直到遇到第一个范围条件列。前面提到的列在WHERE子句中都是等于条件,但age列则多半是范围查询(例如查找年龄在18~25岁之间的人)。当然,也可以使用IN()来代替范围查询,例如年龄条件改写为IN(18,19,20,21,22,23,24,25)但不是所有的范围查询都可以转换。这里描述的基本原则是,尽可能将需要做范围查询的列放到索引的后面,以便优化器能使用尽可能的索引列。前面提到可以在索引中假如更多的列,并通过IN()方式覆盖那些不在WHERE子句中的列。但这种技巧也不能滥用,否则可能会带来麻烦。因为每额外增加一个IN()条件,优化器需要做的组合都将以指数形式增加,最终可能会极大地降低查询性能。考虑下面地子句:

WHERE eye_color IN ('brown', 'blue','hazel') AND hair_color IN ('black','red','blonde','brown') AND sex IN('M','F')

优化器则会转换成4x3x2=24种组合,执行计划需要检查WHERE子句中所有地24种组合。对于MySQL来说,24种组合并不是很夸张,但如果组合数达到上千个则需要特别小心。老版本的MySQL在IN()组合条件过多的时候会有很多问题。查询优化可能需要花很多时间,并消耗大量的内存。新版本的MySQL在组合数超过一定数量后就不再进行执行计划评估了,这可能会导致MySQL不能很好地利用索引。

避免多个范围条件

假设我们有一个last_online列并系统通过下面的查询显示在过去几周上线过的用户:

WHERE eye_color IN ('brown','blue','hazel')
AND hair_color IN('blackj','red','blonde','brown')
AND sex IN ('M','F')
AND last_online > DATE_SUB(NOW, INTERVAL 7 DAY)
AND age BETWEEN 18 AND 25

什么是范围条件?
从EXPLAIN的输出很难区分MySQL是要查询范围值还是查询列表值.EXPLAIN使用同样的词"range"来描述这两种情况.例如,从type列来看,MySQL会把下下面这种查询当作是"range"类型:

mysql> EXPLAIN SELECT actor_id FROM sakila.actor WHERE actor_id > 45\G
*************************** 1. row ***************************id: 1select_type: SIMPLEtable: actorpartitions: NULLtype: range
possible_keys: PRIMARYkey: PRIMARYkey_len: 2ref: NULLrows: 155filtered: 100.00Extra: Using where; Using index
1 row in set, 1 warning (0.00 sec)

但是下面这条查询呢?

mysql> EXPLAIN SELECT actor_id FROM sakila.actor WHERE actor_id IN(1,4,99)\G
*************************** 1. row ***************************id: 1select_type: SIMPLEtable: actorpartitions: NULLtype: range
possible_keys: PRIMARYkey: PRIMARYkey_len: 2ref: NULLrows: 3filtered: 100.00Extra: Using where; Using index
1 row in set, 1 warning (0.00 sec)

从EXPLAIN的结果是无法区分这两者的,但可以从值的范围和多个等于条件来得出不同。在我们看来,第二个查询就是多个等值条件查询的。我们不是挑剔:这两种访问效率是不同的。对于范围条件查询,MySQL无法再使用范围列后面的其他索引列了,但是对于"多个等值条件查询"则没有这个限制

这个查询有一个问题:它有两个范围条件,last_online列和agelie,MySQL可以使用last_online列索引或者age列索引,但无法同时使用它们。如果条件中只有last_online而没有age,那么我们可能考虑再索引的后面加上last_online列。这里考虑如果我们无法把age字段转换为一个IN()的列表,并且仍要求对于同时有last_online和age这两个维度的范围查询的速度很快,那该怎么办?答案是,很遗憾没有一个直接的办法能够解决这个问题。但是我们能够将其中的一个范围查询转换为一个简单的等值比较。为了实现这一点,我们需要事先计算好一个active列,这个字段由定时任务来维护。当用户每次登录时,将杜英值设置为1,并且将过去连续七天未曾登录的用户的值设置为0.
这个方法可以让MySQL使用(active,sex,country,age)索引。active列并不是完全精确的,但是对于这类查询来说,对精度的要求也没有那么高,如果需要精确数据,可以把last_online列放到WHERE子句,但不加入到索引中。这和起那么通过计算URL哈希值来实现URL的快速查找类似。所以这个查询条件没法使用任何索引,但因为这个条件的过滤性不高,即使在索引中加入该列也没有太大的帮助,换个角度来说,缺乏合适的索引对该查询的影响也不明显。
到目前为止,我们可以看到:如果用户希望同时看到活跃和不活跃的用户,可以在查询中使用IN()列表。我们已经加入了很多这样的列表,但另外一个可选的方案就只能是为不同的组合创建单独的索引。至少需要建立如下的索引:(active,sex.country,age),(active,country,age),(sex,country,age)和(country,age)。这些索引对某个具体的查询来说可能都是更优化的了,但是考虑到索引的维护和额外的空间占用的代价,这个可选方案就不是一个好策略了。
在这个案例中,优化器的特性是影响索引策略的一个很重要的因素。如果未来版本的MySQL能够实现松散索引扫描,就能在一个索引上使用多个范围条件,那也就不需要为上面考虑的这类查询使用IN()列表了

优化排序

最后要介绍的是排序。使用文件排序对小数据集是很快的,但如果一个查询匹配的结果有上百万行的话会怎样?例如如果WHERE子句只有sex列,如何排序?对于那些选择性非常低的列,可以增加一些特殊的索引来做排序。例如,可以创建(sex,rating)索引用于下面的查询:

mysql SELECT <cols>  FROM profiles WHERE sex= 'M'  ORDER BY rating LIMIT 10;

这个查询同时使用了ORDER BY 和LIMIT,如果没有索引的话会很慢。即使有索引,如果用户界面山需要翻页,并且翻页翻到比较靠后时查询也可能非常慢。下面这个查询就通过ORDER BY 和LIMIT偏移量的组合翻页到很后面的时候:

mysql> SELECT <cols> FROM profiles WHERE sex='M' ORDER BY rating LIMIT 100000010

无论如何创建索引,这种查询都是个严重的问题,因为随者偏移量的增加,MySQL需要花费大量的时间来扫描需要丢弃的数据。反范式化、预先计算和缓存可能是解决这类查询的仅有策略。一个更好的办法是限制yoghurt能够翻页的数量,实际上这对用户体验的影响不大,因为用户很少会真正在乎搜索结果的第10 000页。优化这类索引的另一个比较好的策略是使用延迟关联,通过使用覆盖索引查询返回需要的主键,再根据这些主键关联源表获得需要的行。这可以减少MySQL扫那些需要丢弃的行数。下面这个查询显示了如何高效地使用(sex,rating)索引进行排序和分页:

mysql> SELECT <cols> FROM profiles INNER JOIN(SELECT <primary key cols> FROM profiles WHERE x.sex ='M' ORDER BY rating LIMIT 1000000,10) AS x USING(<primary key cols>);

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

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

相关文章

云计算和雾计算

雾计算作为传统集中式数据存储系统&#xff08;云&#xff09;和边缘设备之间的中间层。雾扩展了云&#xff0c;使计算和数据存储更接近边缘。雾由多个节点&#xff08;雾节点&#xff09;组成&#xff0c;并创建一个本地网络&#xff0c;使其成为一个去中心化的生态系统——雾…

如何创建一个Angular项目(超简单)

1、安装Node.js&#xff08;官网Node.js下载&#xff09; 2、运行node -v和npm -v两条命令&#xff08;检验是否下载成功Node.js&#xff09; 3、npm i -g cnpm --registryhttps://registry.npmmirror.com&#xff08;用npm安装cnpm&#xff0c;将镜像源设置为国内镜像源&…

ROS2 (python)构造服务端和客户端

要注意&#xff1a;服务端和客户端的名字要统一 什么是线程死锁 A需要等B把装满水的桶放下 才能把水桶提走 B需要等A把水桶提走才能把自己的装满 假设A和B都要站在位置C工作 A&#xff1a;站在工位C将小桶水倒进大桶里 B&#xff1a;从C位置将装满水的大桶拎走 那么假设时刻…

Next前端是什么

Next前端是什么 在前端开发的浩瀚星空中&#xff0c;Next前端如同一颗璀璨的明星&#xff0c;吸引着无数开发者的目光。那么&#xff0c;Next前端究竟是什么呢&#xff1f;它为何能在前端领域掀起如此波澜&#xff1f;接下来&#xff0c;我们将从四个方面、五个方面、六个方面…

制作一个简单HTML旅游网站(HTML+CSS+JS)云南旅游网页设计与实现5个页面

一、&#x1f468;‍&#x1f393;网站题目 旅游&#xff0c;当地特色&#xff0c;历史文化&#xff0c;特色小吃等网站的设计与制作。 二、✍️网站描述 云南旅游主题的网页 一共七个个页面 - 旅游网页使用html css js制作 有banana图 - 页面可以相互跳转 包含表单 三级页面…

Laravel 富文本内容

Laravel 获取富文本的纯文本内容-CSDN博客 Laravel 富文本内容里面的图片添加前缀URL-CSDN博客 Laravel 富文本图片的style样式删除-CSDN博客. 富文本字体font-famly删除 $data preg_replace(/(<[^>])style["\][^"\]*font-family:[^"\]*["\]([^&…

Shopee爆款打造核心运营方法,下一个大卖就是你

课程下载&#xff1a;Shopee爆款打造核心运营方法&#xff0c;下一个大卖就是你-课程网盘链接提取码下载.txt资源-CSDN文库 更多资源下载&#xff1a;关注我。 课程内容&#xff1a; 001.1-爆款产品的选择,mp4 002.2-依据宗教信仰和消费禁忌选品.mp4 003.3-刻画消费者画像…

C++设计模式-桥接模式

运行在VS2022&#xff0c;x86&#xff0c;Debug下。 29. 桥接模式 桥接模式将抽象与实现分离&#xff0c;使二者可以独立地变化。 应用&#xff1a;如在游戏开发中&#xff0c;多个角色和多个武器交叉组合时。可以使用桥接模式&#xff0c;定义角色抽象类&#xff0c;武器抽象…

如何跨渠道分析销售数据 - 7年制造业销售经验小结

如何跨渠道分析销售数据 - 7年制造业销售经验小结&#xff08;1&#xff09; 【前言】 在我过去7年销售工作生涯中&#xff0c;从第一年成为公司销冠后&#xff0c;我当时的确自满的一段时间&#xff0c;认为自己很了不起。但是第一年的销售业绩并没有拿到提成&#xff0c;最…

2024-06-02 问AI: 在大语言模型中,什么是multi agent?

文心一言 在大语言模型中&#xff0c;Multi-Agent&#xff08;多智能体&#xff09;是指由多个具有自主决策和交互能力的智能体&#xff08;Agent&#xff09;组成的系统。这些智能体能够相互协作、竞争或协商&#xff0c;以完成共同或各自的任务。以下是关于Multi-Agent在大语…

爱情的短视频短片:四川京之华锦信息技术公司

爱情的短视频短片&#xff1a;情感瞬间的浓缩与绽放 在数字化时代&#xff0c;短视频以其短小精悍、直击人心的特点&#xff0c;迅速占领了互联网的高地。而在这些纷繁复杂的短视频内容中&#xff0c;关于爱情的短视频短片更是以其独特的魅力&#xff0c;吸引了无数观众的目光…

【U-Net验证】逐元素乘积将特征投射到极高维隐式特征空间的能力

写在前面&#xff1a;本博客仅作记录学习之用&#xff0c;部分图片来自网络&#xff0c;如需使用请注明出处&#xff0c;同时如有侵犯您的权益&#xff0c;请联系删除&#xff01; 文章目录 前言网络结构编码结构解码结构代码 实验实验设置w/o-ReLU的性能比较with-ReLU的性能比…

【Kotlin】简单介绍与使用kotlin

&#x1f34e;个人博客&#xff1a;个人主页 &#x1f3c6;个人专栏&#xff1a;Kotlin ⛳️ 功不唐捐&#xff0c;玉汝于成 目录 前言 正文 特点 变量和常量 数据类型和类型推断 函数 字符串模板 条件表达式 空安全 when 表达式 循环 我的其他博客 前言 Kotlin是…

C语言编程可以拦截弹窗吗:深入探索与解析

C语言编程可以拦截弹窗吗&#xff1a;深入探索与解析 在编程的世界里&#xff0c;C语言以其简洁、高效和接近硬件的特性而著称。然而&#xff0c;当涉及到弹窗拦截这样的任务时&#xff0c;很多人可能会对C语言的能力产生疑问。那么&#xff0c;C语言编程真的可以拦截弹窗吗&a…

适合技术小白学习的项目1840java swing社团管理系统myeclipse开发Mysql数据库CS结构java编程

一、源码特点 java swing社团管理系统 是一套完善的窗体设计系统&#xff0c;对理解SWING java 编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;&#xff0c;系统主要采用C/S模式开发。 应用技术&#xff1a;javamysql 开发工具&#xff1a;Myecl…

Flutter开发效率提升1000%,Flutter Quick教程之对被遮挡的组件进行编辑

1&#xff0c;有些时候&#xff0c;有的widget会被其他widget所遮挡&#xff0c;那么&#xff0c;我们如何选中被遮挡的Widget?如下面这张图。上面是一个Text&#xff0c;外面包裹着一个Container&#xff0c;这时候点击事件会被Text所拦截&#xff0c;那么&#xff0c;如何选…

零基础画师文创运营变现课,从0基础到入门一步步提升(46节课)

课程下载&#xff1a;零基础画师文创运营变现课&#xff0c;从0基础到入门一步步提升&#xff08;46节课&#xff09;-课程网盘链接提取码下载.txt资源-CSDN文库 更多资源下载&#xff1a;关注我。 课程内容&#xff1a; 01 我的二十五年,mp4 02 古法裁剪与新古法裁剪,mp4 …

重塑电商科技版图:从传统架构迈向DDD的华丽蜕变之路

关注微信公众号 “程序员小胖” 每日技术干货&#xff0c;第一时间送达&#xff01; 引言 随着电子商务行业的蓬勃发展&#xff0c;传统的电商系统架构面临着诸多挑战&#xff0c;如扩展性不足、维护成本高、响应市场变化慢等。领域驱动设计&#xff08;Domain-Driven Design&a…

动规算法-地下城游戏

在刷题练习专栏中&#xff0c;已经写了两篇文章实现对动态规划入门题目的讲解了&#xff0c;动态规划这类题目很难很好的掌握&#xff0c;今天给大家带来稍微深入的题目&#xff0c;帮助大家更好的理解动态规划的算法思想&#xff0c;加深对该算法的理解&#xff0c;建议看每道…

渗透测试之Web安全系列教程(二)

今天&#xff0c;我们来讲一下Web安全&#xff01; 本文章仅提供学习&#xff0c;切勿将其用于不法手段&#xff01; 目前&#xff0c;在渗透测试领域&#xff0c;主要分为了两个发展方向&#xff0c;分别为Web攻防领域和PWN&#xff08;二进制安全&#xff09;攻防领域。Web…