总结:同样也是一颗 B+ 树,data 域保存数据记录的地址。因此,MyISAM 的索引的算法首先按照 B+ 树搜索算法搜索索引,如果指定的 Key 存在,则取出其中 data 域的值,然后读取相关记录。
MyISAM 的索引方式也叫做 “非聚集” 的,之所以这么称呼是为了与 InnoDB 的聚集索引区分的。
InnoDB 索引实现
虽然 InnoDB 也使用 B+ 树作为索引结构,但是具体实现方式与 MyISAM 截然不同。
第一个区别是 InnoDB 的数据文件本身就是索引文件。从上文可以知道,MyISAM 索引文件和数据文件是分离的,索引文件仅保存数据记录地址。而在 InnoDB 中,表数据文件本身就是 B+ 树组织的一个索引结构,这棵树的叶子节点 data 域保存了完整的数据结构。这个索引的 key 是数据表的主键,因此 InnoDB 表数据文件本身就是主索引。
上图是 InnoDB 主索引的示意图,可以看到叶节点包含了完整的数据记录。这种索引也叫做聚集索引。因为 InnoDB 的数据文件本身要按主键聚集,所以 InnoDB 要求必须有主键索引(MyISAM 可以没有)。如果没有显示指定,MySql 系统会自动选择一个可以唯一标识数据记录的列作为主键,如果不存在这种列,MySQL 自动为 InnoDB 表生成一个隐含字段作为主键。
第二个与 MyISAM 索引的不同是 InnoDB 的辅助索引 data 域存储相应记录主键的值而不是地址。InnoDB 的所有辅助索引都引用主键作为 data 域。
这里以英文字符的 ASCII 码作为比较标准。聚集索引这种实现方式使得按主键搜索十分搞笑,但是辅助索引搜索需要两遍索引:先检索辅助索引获得主键,然后用主键索引检索记录。
熟悉了 InnoDB 的索引实现后,就明白了为什么不建议使用过长的字段作为主键,因为所有辅助索引都使用主索引,过长的主索引会令辅助索引变的过大。再比如,用非单调的字段作为 InnoDB 的主键不是个好主意,非单调的主键造成插入新纪录时数据文件维持 B+ 树的特性而频繁的分裂调整,使用自增字段作为主键是一个很好的选择。
InnoDB索引和MyISAM索引的区别:
一是主索引的区别,InnoDB的数据文件本身就是索引文件。而MyISAM的索引和数据是分开的。
二是辅助索引的区别:InnoDB的辅助索引data域存储相应记录主键的值而不是地址。而MyISAM的辅助索引和主索引没有多大区别。
建立索引常用技巧最左匹配原则,非常重要的原则,mysql 会一直向右匹配直到遇到范围查询(<,>,between,like)就停止匹配,比如 a=1 and b = 2 and c > 3 and b = 4 如果建立(a,b,c,d)顺序的索引,d 是用不到索引的,如果建立(a,b,d,c)的索引都可以用到。
= 和 in 可以乱序,比如 a = 1 and b = 2 and c = 3 建立 (a,b,c)所以可以任意顺序。
尽量选择区分度高的列作为索引。字段不重复的比例不能太小,唯一键的区分度是 1,而一些状态,性别字段在大数据面前区分度就是 0。
索引不能参与计算。比如 from_unixtime(create_time) = ’2014-05-29’ 就不能使用到索引,原因很简单,b+ 树中存的都是数据表中的字段值,但进行检索时,需要把所有元素都应用函数才能比较,显然成本太大,应该把语句写成 create_time = unix_timestamp(’2014-05-29’)。
SQL 调优一般要进行 SQL 调优,那么就是有慢查询的 SQL,系统或者 server 可以开启慢查询日志。
通过慢查询记录能够记录一些执行时间比较久的 SQL 语句,找出这些语句不意味着工作结束了,我们通常使用 explain 这个命令来查看这些 SQL 语句的执行计划,查看该 SQL 语句有没有使用索引,有没有做全表扫描。
mysql> explain select * from servers; +----+-------------+---------+------+---------------+------+---------+------+------+-------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+---------+------+---------------+------+---------+------+------+-------+ | 1 | SIMPLE | servers | ALL | NULL | NULL | NULL | NULL | 1 | NULL | +----+-------------+---------+------+---------------+------+---------+------+------+-------+ 1 row in set (0.03 sec)各个字段的含义:
id:表示 SQL 执行的顺序的标识。
select_type:表示产讯中每个 select 子句的类型。
table:显示这一行的数据是关于哪张表的,有时不是真实的表名字。