1.索引基础

索引对于良好的性能非常关键。尤其是当表中的数据量越来越大时,索引对性能的影响愈发重要。但是不恰当的索引随着数据量的增加,也会使整个数据库的性能下降。

举个例子:

select a from b where id = ;

如果在id上建立索引,则Mysql会使用该索引找到id为5的行,也就是说,Mysql现在索引按值进行查找,然后返回所有包含该值的数据行。索引也可以包含一列或者多列,列的顺序也十分重要,因为Mysql只能高效地使用索引的最左前缀列。

索引优化应该是查询性能优化最有效的手段了,一个“最优”的索引有时比一个“好的”索引性能要好两个数量级,所以索引的学习无论对开发者或者DBA来说都极为重要。

2.索引类型

B-Tree索引

人们在谈论索引时,若无指定,一般为B-Tree类型的索引,Mysql大部分引擎支持B-Tree索引,但在不同的存储引擎中,B-Tree也可能以不同存储结构实现,比如InnoDB则使用B+Tree。存储引擎以不同的方式使用B-Tree索引,性能优劣各有不同。

B-Tree通常意味着所有的值都是按顺序存储的,并且每一个叶子页到根的距离相同。下图为B-Tree(B+Tree)索引的抽象表示,大致反映了InnoDB索引是如何工作的。MyISAM使用的结构有所不同,但基本思想是类似的。

这种类型的索引的好处是查询时不需要进行全盘扫描而是从根节点开始搜索,通过比较找到相应的值并进入下层子节点。所以B-Tree比较适合查找范围数据,例如像“找出所有I到K开头的名字”。

假设有如下数据表:

CREATE TABLE People (
last_name varcher() not null,
first_name varcher() not null,
dob date not null,
gender enum('m', 'f') not null,
key(last_name, first_name, dob)
);

对于表中的每一行数据,索引中包含了last_name,first_name,dob列的值,下图显示了该索引是如何组织数据的存储的。

  • 这里要注意的是,索引对多个值进行排序的依据是CREATE TABLE语句中定义时列的顺序(比如上文的顺序为last_name,first_name,dob)。

下面列举一些B-Tree索引的常用的查询类型:

  • 全值比配 全值匹配指的是和索引中的所有列进行匹配,例如索引可用于查找姓名为Cuba Allen、出生于1960-01-01的人
  • 匹配最左前缀 例如查找所有姓Allen的人,即只使用索引的第一列
  • 匹配列前缀 也可以只匹配某一列的值的开头部分。例如前面提到的索引可用于查找所有以J开头的姓的人。这里也只使用了索引的第一列
  • 匹配范围值 例如前面提到的索引可用于查找姓在Allen和Barrymore之间的人。这里也只使用了索引的第一列
  • 精确匹配某一列并范围匹配另外一列 例如像查找所有姓为Allen,并且名字是字母K开头的人。即第一列last_name全匹配,第二列first_name范围匹配
  • 只访问索引的查询 即查询只需要访问索引,而无须访问数据行。

除了按值查找外,索引还可以用于ORDER BY操作。

下列关于B-Tree索引的一些限制:

  • 如果不是按照索引的最左列开始查找,则无法使用索引。例如上面例子中无法用于查找名字为Bill的人,也无法查找某个特定生日的人,因为这两列都不是最左数据列。
  • 不能跳过索引中的列,例如查找Smith并且在某个特定生日的人,如果不指定first_name,则Mysql只能用上索引的第一列
  • 如果查询中有某个列的范围查询,则其右边的列都无法使用索引优化查找。比如 where last_name='Smith' AND first_name LIKE '%J%' AND dob= '1976-01-01',这个查询只能用上前两列索引,但如果范围查询数量有限,则可以优化为多个等于条件进而使用上索引

哈希索引

哈希索引基于哈希表实现,只有精确匹配索引所有列的查询才有效。在Mysql中只有Memory引擎显式支持哈希索引。

比如: SELECT A FROM B WHERE name='PETER';

Mysql会先计算'PETER'的哈希值,并使用该值寻找对应的指针记录。因为索引自身只需存储对应的哈希值,所以哈希索引查找速度非常快,但是也有一些限制:

  • 哈希索引只包含哈希值和行指针,不存储字段值,所以不能使用索引中的值来避免读取行
  • 哈希索引不是顺序存储,无法用于排序
  • 哈希索引也不支持索引列匹配查找,例如KEY(A,B),如果查询只有数据列A则无法使用该索引
  • 哈希索引只支持等值比较查询
  • 当出现哈希冲突时,存储引擎必须便利链表中所有的行指针,直到找到匹配的行
  • 哈希冲突很多的话,一些索引维护操作的代价也会很高

因为这些限制,哈希索引使用的场景有限,而一旦适合哈希索引时,则它带来的性能提升将非常高。

当然,对于InnoDB来说也可以创建一个伪哈希列来进行排序查找也是可以的。

下面有个实例,例如需要存储大量URL,如果使用B-Tree来存储URL,存储的内容会很大,因为URL本身很长,正常情况下会有如下查询:

SELECT ID FORM URL WHERE url='http://www.baidu.com'

若删除原来的URL列上的索引,而新增一个被索引的url_crc列,使用CRC32做哈希,就可以使用下面的方式查询:

SELECT ID FROM URL WHERE url='http://www.baidu.com' AND url_crc=CRC32("http://www.baidu.com");

这样做的性能会比单独在url列上开索引高很多,但缺陷就是需要维护哈希值,可以手动维护,也可以使用触发器实现,例如:

//创建表
CREATE TABLE pseudo hash(
id int unsigned not null auto_increment,
url archer() not null,
url_crc int unsigned not null default ,
primary key(id)
);
//创建触发器
DELIMITER //
CREATE TRIGGER pseudohash_crc_ins BEFORE INSERT ON pseudohash FOR EACH ROW BEGIN
SET NEW.url_crc=crc32(NEW.url);
END;
//
CREATE TRIGGER pseudohash_crc_upd BEFORE UPDATE ON pseudohash FOR ROW BEGIN
SET NEW.url_crc=crc32(NEW.url);
END;
//
DELIMITER ;

如果数据表非常大,crc32可能也会出现大量的哈希冲突,这个时候也可以使用其他方案代替,比如md5

处理哈希冲突时,必须在WHERE子句中包含常量值:

SELECT ID FROM URL WHERE url_crc=crc32('http://www.baidu.com') AND url='http://www.baidu.com';

还有一些其他的索引类型,例如空间数据索引,全文索引,这里暂时不介绍了,大家可以自行搜索。

Mysql优化之创建高性能索引(一)的更多相关文章

  1. Mysql优化之创建高性能索引(二)

    1.索引的优点 索引可以让服务器快速地定位到表的指定位置.总结下来有三大优点: 索引大大减少了服务器需要扫描的数据量 索引可以帮助服务器避免排序和临时表 索引可以将随机I/O变为顺序I/O 2.高性能 ...

  2. Mysql优化之创建高性能索引(三)

    聚蔟索引 聚蔟索引并不是一种单独的索引类型,而是一种数据存储方式.Innodb的聚蔟索引在同一结构保存了B-Tree索引和数据行. 当表有聚蔟索引时,它的数据行实际上存放在索引的叶子页中.下图展示了聚 ...

  3. php面试专题---16、MySQL创建高性能索引考点

    php面试专题---16.MySQL创建高性能索引考点 一.总结 一句话总结: 注意:只写精品 1.索引的基础? 类似书籍的目录:索引类似于书籍的目录,要想找到一本书的某个特定主题,需要先查找书的目录 ...

  4. mysql笔记02 创建高性能的索引

    创建高性能的索引 1. 索引(在MySQL中也叫做"键(key)")是存储引擎用于快速找到记录的一种数据结构. 2. 索引可以包含一个或多个列的值.如果索引包含多个列,那么列的顺序 ...

  5. MySQL 创建高性能索引

    索引是存储引擎用于快速找到记录的一种数据结构.除了加速查找,索引在其他方面也有一些有用的属性.索引对于良好的性能非常关键.尤其是当表中的数据量越来越大时,索引对性能的影响愈发重要.在数据量较小且负载较 ...

  6. MySQL创建高性能索引

    参考<高性能MySQL>第3版 1 索引基础 1.1 索引作用 在MySQL中,查找数据时先在索引中找到对应的值,然后根据匹配的索引记录找到对应的数据行,假如要运行下面查询语句: 如果在u ...

  7. 《高性能MySQL》——第五章创建高性能索引

    1.创建索引基本语法格 在MySQL中,在已经存在的表上,可以通过ALTER TABLE语句直接为表上的一个或几个字段创建索引.基本语法格式如下: ALTER TABLE 表名 ADD [UNIQUE ...

  8. PHP面试 MySQL创建高性能索引考点

    MySQL索引 MySQL索引的基础和类型 索引的基础:索引类似于书籍的目录,要想找到一本书的某个特定篇章,需要查找书的目录,定位对应的页码 存储引擎使用类似的方式进行数据查询,先去索引当中找到对应的 ...

  9. [MySQL-笔记]创建高性能索引

    索引,MySQL中也叫“键”,是存储引擎中用于快速找到记录的一种数据结构,具体的工作方式就像书本中的索引一样,但是具体的实现方式会有差别. 一.索引分类 B-Tree索引: 优点: MyISAM中,索 ...

随机推荐

  1. SQLSERVER和sybase的差异

    sybase sqlserver *= left join =* right join

  2. 设置secureCRT中vim的字体颜色

    1.在/etc/vimrc新增以下一行 syntax on 注:上述方法对root用户无效,原因为在一般用户中,alias vi=vim,而在root用户中默认无此设置,因此若需要root用户也显示颜 ...

  3. Ecstore中如何调用发起Ajax请求

    Ecstore的JS框架使用了mootools,所以ajax调用也使用mootools中的Request组件. 语法: var myRequest = new Request([options]); ...

  4. 淘管 ERP项目与淘宝对接中产生的若干问题及处理办法

    现象:ERP绑定淘宝后,下载商品数据时如果成功,ajax不断尝试重发. 原因:  /app/taoapi/lib/top/TopClient.php 中的curl()方法成功后,返回空值,而前端收到空 ...

  5. NASM mode for Emacs

    NASM mode for Emacs   Quick post for those Emacs users out there.   The common assembler used on GNU ...

  6. Ext.getCmp()的简单使用

    Ext.getCmp(Ext组件ID),根据Ext组件的ID选择EXT组件. 例如:点击Panel->toolbar上的button改变Panel的标题 Ext.onReady(function ...

  7. 2015第10周三jquery ui position

    jQuery UI API - .position() 所属类别 方法重载(Method Overrides) | 方法(Methods) | 实用工具(Utilities) 用法 描述:相对另一个元 ...

  8. 在Activity中响应ListView内部按钮的点击事件的两种方法!!!

    在Activity中响应ListView内部按钮的点击事件的两种方法 转载:http://www.cnblogs.com/ivan-xu/p/4124967.html 最近交流群里面有人问到一个问题: ...

  9. 操作系统基本概念(内核态与用户态、操作系统结构)-by sixleaves

    内核态与用户态(为什么存在这种机制.程序应处于哪个状态.如何判断当前所处状态.哪些功能需要内核态.如何实现这种机制) 1.首先我们应该思考清楚为什么会有内核态和用户态?(为什么存在这种机制) 因为计算 ...

  10. 安装配置MongoDB数据库

    一.关闭SElinux.配置防火墙 1.vi /etc/selinux/config #SELINUX=enforcing #注释掉 #SELINUXTYPE=targeted #注释掉 SELINU ...