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. Niagara AX之在Station下显示Home节点

    默认的Station下是没有Home节点的,那么,这个Home节点是怎么添加上去的呢? 注意Home后面的描述(Description):“Navigation tree defined by nav ...

  2. (原)Eclipse的java中文件读写

    1 在<uses-sdk…/>下面添加permission <uses-sdk android:minSdkVersion="16" android:target ...

  3. 如何使用Assetic进行文件管理

    安装和配置Assetic 从symfony2.8开始,Assetic就不再被包括在symfony标准版.使用任何Assetic的特性之前需要安装AsseticBundel,在命令行执行下面命令: $ ...

  4. git merge 分支

    把master merge到apple_campus1.git stash2.git checkout master3.git pull4.git checkout apple_campus5.git ...

  5. Pie(hdu 1969 二分查找)

    Pie Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submiss ...

  6. [statsvn]-svn代码量统计

    用statasvn进行代码量统计的时候,第一步需要获取到项目的日志,但是我本机的svn1.4没有安装命令行,重新运行1.4的安装包也没有命令行的选项... 那就升级到最新的svn1.8好了,下载最新的 ...

  7. OC 代理 协议 委托 数据源的概念

    (网摘) OBJC 中的 protocol 相当于 java 里的接口,delagate 就是接口的实现类(C中的回调类似 ): 数据源就是对象遵循了存储数据的协议,可以存储使用数据 协议表示了方法可 ...

  8. Log4net 可直接使用的配置

    config配置 <xml version="1.0"> <configuration> <configSections> <!--配置一 ...

  9. USB系列之八:透过ASPI执行SCSI命令

    在<USB系列之七>里我们介绍了ASPI的规范,并对一系列ASPI的命令做了测试,其中的02号命令是执行SCSI命令,我们专门在这篇文章中介绍,在<USB系列七>中,我们已经了 ...

  10. USB_scsi 之旅

    现在总结一下scsi,scsi协议有很多,所以只总结这次在usb mass storage里面用到的协议,主要包括inquiry,format , read write等等命令. 下面会一个一个总结. ...