索引使用案例

支持多种过滤条件

假设要设计一个在线约会网站,用户信息表有很多列,包括国家、地区、城市、性别、眼睛颜色,等等。网站必须支持上面这些特征的各种组合来搜索用户,还必须允许根据用户的最后在线时间、其他会员对用户的评分等对用户进行排序并对结果进行限制。如何设计索引满足上面的复杂需求呢?

现在需要看看哪些列选择性更高,哪些列在WHERE 子句中出现得最频繁。country、sex 列的选择性通常不高,但可能很多查询都会用到。所以考虑到使用的频率,建议在创建不同组合索引的时候将(sex,country )列作为前缀。但根据经验不是不应该在选择性低的列上创建索引的吗?这么做有两个理由:

  • 第一点,如前所述几乎所有的查询都会用到sex 列。
  • 更重要的一点是,索引中加上这一列也没有坏处,即使查询没有使用sex列也可以通过下面的“诀窍”绕过。这个“诀窍”就是:如果某个查询不限制性别,那么可以通过在查询条件中新增AND SEX IN('m','f') 来让MySQL选择该索引。

    接下来,需要考虑其他常见WHERE 条件的组合,并需要了解哪些组合在没有合适索引的情况下会很慢。(sex,country,age )上的索引就是一个很明显的选择,另外很有可能还需要(sex,country,region,age )和(sex,country,region,city,age)这样的组合索引。

    将aging放在索引的最后是因为age列多半是范围查询,而查询只能使用索引的最左前缀,直到遇到第一个范围条件列。前面的列在where子句中基本都是等于条件,故放置在age之前。

如何为一些生僻的搜索条件(比如has_pictures、eye_color、hair_color 和education)来设计索引呢?这些列的选择性高、使用也不频繁,可以选择忽略它们,让MySQL多扫描一些额外的行即可。

避免多个范围条件

从EXPLAIN 的输出很难区分MySQL是要查询范围值(>,<),还是查询列表值(in,not in)。EXPLAIN 使用同样的词“range”来描述这两种情况,但可以从值的范围和多个等于条件来得出不同。在我们看来,列表查询就是多个等值条件查询。这两种访问效率是不同的。对于范围条件查询,MySQL无法再使用范围列后面的其他索引列,但是对于“多个等值条件查询”则没有这个限制。

优化排序

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

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

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

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

无论如何创建索引,这种查询都是个严重的问题。因为随着偏移量的增加,MySQL需要花费大量的时间来扫描需要丢弃的数据(需要将行数据加载出来?)。一个更好的办法是限制用户能够翻页的数量,实际上这对用户体验的影响不大,因为用户很少会真正在乎搜索结果的第10000页。

优化这类索引的另一个比较好的策略是使用延迟关联,通过使用覆盖索引查询返回需要的主键,再根据这些主键关联原表获得需要的行。这可以减少MySQL扫描那些需要丢弃的行数。下面这个查询显示了如何高效地使用(sex,rating )索引进行排序和分页:

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

维护索引

减少索引和数据的碎片

B-Tree索引可能会碎片化,这会降低查询的效率。碎片化的索引可能会以很差或者无序的方式存储在磁盘上。

根据设计,B-Tree需要随机磁盘访问才能定位到叶子页,所以随机访问是不可避免的。然而,如果叶子页在物理分布上是顺序且紧密的,那么查询的性能就会更好。否则,对于范围查询、索引覆盖扫描等操作来说,速度可能会降低很多倍;对于索引覆盖扫描这一点更加明显。

行碎片(Row fragmentation),这种碎片指的是数据行被存储为多个地方的多个片段中。即使查询只从索引中访问一行记录,行碎片也会导致性能下降,InnoDB不存在这种碎片。

行间碎片(Intra-row fragmentation),行间碎片是指逻辑上顺序的页,或者行在磁盘上不是顺序存储的。行间碎片对诸如全表扫描和聚簇索引扫描之类的操作有很大的影响,因为这些操作原本能够从磁盘上顺序存储的数据中获益。

剩余空间碎片(Free space fragmentation),剩余空间碎片是指数据页中有大量的空余空。这会导致服务器读取大量不需要的数据,从而造成浪费。

对于MyISAM表,这三类碎片化都可能发生。但InnoDB不会出现短小的行碎片;InnoDB会移动短小的行并重写到一个片段中。可以通过执行OPTIMIZE TABLE 或者导出再导入的方式来重新整理数据,这对多数存储引擎都是有效的。

MySQL 索引使用案例的更多相关文章

  1. MySQL索引优化案例

    这里我们分成三种情况进行分析,分别是单表,两表,三表 1.单表 CREATE TABLE IF NOT EXISTS `article`( `id` ) NOT NULL PRIMARY KEY AU ...

  2. MySQL索引优化案例浅析

    MySQL是关系型数据库的一种,查询功能强,数据一致性高,数据安全性高,支持二级索引.但是性能比起非关系型数据库稍弱,特别是百万级以上的数据,很容易出现查询慢的现象.这时候要分析慢的原因,一般情况下是 ...

  3. Mysql 索引案例学习

    理解索引最好的办法是结合示例,所以这里准备了一个索引的案例. 假设要设计一个在线约会网站,用户信息表有很多列,包裹国家,地区,城市,性别,眼睛颜色,等等.完整必须支持上面这些特征的各种组合来搜索用户, ...

  4. MySQL数据库索引类型、MySQL索引的优化及MySQL索引案例

    关于MySQL索引的好处,如果正确合理设计并且使用索引的MySQL是一辆兰博基尼的话,那么没有设计和使用索引的MySQL就是一个人力三轮车.对于没有索引的表,单表查询可能几十万数据就是瓶颈,而通常大型 ...

  5. MySQL全面瓦解25:构建高性能索引(案例分析篇)

    回顾一下上面几篇索引相关的文章: MySQL全面瓦解22:索引的介绍和原理分析 MySQL全面瓦解23:MySQL索引实现和使用 MySQL全面瓦解24:构建高性能索引(策略篇) 索引的十大原则 1. ...

  6. MySQL索引原理及慢查询优化

    原文:http://tech.meituan.com/mysql-index.html 一个慢查询引发的思考 select count(*) from task where status=2 and ...

  7. (转)MySQL索引原理及慢查询优化

    转自美团技术博客,原文地址:http://tech.meituan.com/mysql-index.html 建索引的一些原则: 1.最左前缀匹配原则,非常重要的原则,mysql会一直向右匹配直到遇到 ...

  8. MySQL索引原理及慢查询优化 转载

    原文地址: http://tech.meituan.com/mysql-index.html MySQL凭借着出色的性能.低廉的成本.丰富的资源,已经成为绝大多数互联网公司的首选关系型数据库.虽然性能 ...

  9. MySQL索引原理及慢查询优化(转)

    add by zhj:这是美团点评技术团队的一篇文章,讲的挺不错的. 原文:http://tech.meituan.com/mysql-index.html MySQL凭借着出色的性能.低廉的成本.丰 ...

随机推荐

  1. kubernetes的存活探针和就绪探针

    1.存活探针 使用Kubernetes的一个主要好处是,可以给Kubernetes-个容器列表来由其保持容器在集群中的运行.可以通过让Kubernetes创建pod资源,为其选择一个工作节点并在该节点 ...

  2. Linux 安装 git

    安装方法参考:http://www.jb51.net/os/RedHat/149653.html 具体内容: 在安装Git之前,需要先安装一些依赖包,安装依赖包之前可以先检查下是否已经安装. shel ...

  3. 应用CRM的自动化功能为什么备受推崇

    相信每个销售团队都遇到过这样的问题:在跟进新客户的时候顾此失彼,在跟踪一个客户的时候,转眼就忘记了另一个客户.这种情况很常见,但是每个新客户都有潜在的价值,我们该如何做,才能避免错失商机?CRM客户管 ...

  4. coretext简单使用

    相对于UIKit,使用coretext绘制文本效率高,具有更高的自由度,可随时插入图片,增加文本点击事件等. 1.增加文本的点击事件 思路:定义UILabel子类,设置可点击的富文本range及其他属 ...

  5. 题解 SP3591 PATHEADS - Patting Heads

    类似桶排 先看有多少头奶牛抽出这个数 再看这个数的奶牛能拍多少人的头(别忘了-1,自己不能拍自己) 最后根据输入输出 110ms #include<bits/stdc++.h> using ...

  6. mindmaster导出markdown文档

    mindmaster支持多终端同步,10M免费云空间对于免费用户来说够用了,又给我的IPad增加了生产力,赞! 每次在写文章之前我都会先用mindmaster的思维导图把结构写好,然后根据结构大纲写文 ...

  7. Spring Boot(一):如何使用Spring Boot搭建一个Web应用

    Spring Boot Spring Boot 是Spring团队旗下的一款Web 应用框架 其优势可以更快速的搭建一个Web应用 从根本上上来讲 Spring Boot并不是什么新的框架技术 而是在 ...

  8. SuperEdge 易学易用系列-SuperEdge 简介

    关于 SuperEdge SuperEdge 是由腾讯.Intel.VMware.虎牙直播.寒武纪.首都在线和美团等多家公司共同发起的边缘容器管理系统,它基于原生 Kubernetes.针对边缘计算和 ...

  9. Python基础之魔术方法(一个序列容器的魔术方法)

    # 创建自己想要的序列容器魔术方法'''__len__():调用len(obj)函数会调用这个魔术方法__getitem__(self,key):在使用下标操作temp['key']以及切片操作的时候 ...

  10. 微信小程序云开发-云存储-上传文件(图片/视频)到云存储 精简代码

    说明 图片/视频这类文件是从客户端会话选择文件. 一.wxml文件添加if切换显示 <!--上传文件到云存储--> <button bindtap="chooseImg&q ...