MySQL数据库索引

Posted Guangxiang Jia

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySQL数据库索引相关的知识,希望对你有一定的参考价值。

 

1 索引概述

所有mysql列类型都可以被索引,对相关列使?索引是提?SELECT操作性能的最佳途径。

根据存储引擎可以定义每个表的最?索引数和最?索引长度,每种存储引 擎(如 MyISAM、InnoDB、BDB、MEMORY等)对每个表?少?持16个索引,总索 引长度?少为256字节。?多数存储引擎有更?的限制。

MyISAM和InnoDB存储引擎的表默认创建的都是BTREE索引。MySQL支持对索引字段的前N个字符创建索引(短索引也叫前缀索引)。前缀索引 的长度跟存储引擎相关,对于MyISAM存储引擎的表,索引的前缀长度可以达到1000 字节长,?对于InnoDB存储引擎的表,索引的前缀长度最长是767字节。

MySQL中还支持全文本(FULLTEXT)索引,该索引可以用于全文搜索。但是当前最新版本(5.0)中只有MISQM存储引擎支持FULLTEXT索引。并且只限于CHAR、VARCHAR、TEXT列。索引总是对整列进行的,不支持前缀索引。

默认情况下,MEMORY存储引擎使?HASH索引,但也?持BTREE索引。

2  设计索引的原则
索引的设计可以遵循?些已有的原则,创建索引的时候请尽量考虑符合这些原则,便于提升索引的使?效率,更?效地使?索引。

1:搜索的索引列。最适合索引的列是出现在WHERE?句中的列,或连接? 句中指定的列,?不是出现在SELECT关键字后的选择列表中的列。

2:使?唯?索引。考虑某列中值的分布。索引的列的基数越?,索引的效果越好。例如,存放出??期的列具有 不同值,很容易区分各?。??来记录性别的列,只含有“M”和“F”,则对此列进?索引没有多??处,因为不管 搜索哪个值,都会得出?约?半的?。

3:使?短索引。如果对字符串列进?索引,应该指定?个前缀长度,只要有可能就应该这样做。例如,有?个 CHAR(200)列,如果在前10个或20个字符内,多数值是唯?的,那么就不要对整个列进?索引。对前10个或20个字 符进?索引能够节省?量索引空间,也可能会使查询更快。较?的索引涉及的磁盘 IO 较少,较短的值?较起来更 快。更为重要的是,对于较短的键值,索引?速缓存中的块能容纳更多的键值,因此,MySQL 也可以在内存中容 纳更多的值。这样就增加了找到??不?读取索引中较多块的可能性。

4:利?最左前缀。在创建?个n列的索引时,实际是创建了MySQL可利?的n个索引。多列索引可起?个索引的 作?,因为可利?索引中最左边的列集来匹配?。这样的列集称为最左前缀。

5:不要过度索引。不要以为索引“越多越好”,什么东西都?索引是错误的。每个额外的索引都要占?额外的磁盘 空间,并降低写操作的性能。在修改表的内容时,索引必须进?更新,有时可能需要重构,因此,索引越多,所花 的时间越长。如果有?个索引很少利?或从不使?,那么会不必要地减缓表的修改速度。此外,MySQL 在?成? 个执?计划时,要考虑各个索引,这也要花费时间。创建多余的索引给查询优化带来了更多的?作。索引太多,也 可能会使MySQL选择不到所要使?的最好索引。只保持所需的索引有利于查询优化。

6:对于InnoDB存储引擎的表,记录默认会按照?定的顺序保存,如果有明确定义的主键,则按照主键顺序保 存。如果没有主键,但是有唯?索引,那么就是按照唯?索引的顺序保存。如果既没有主键又没有唯?索引,那么 表中会?动?成?个内部列,按照这个列的顺序保存。按照主键或者内部列进?的访问是最快的,所以InnoDB表 尽量??指定主键,当表中同时有?个列都是唯?的,都可以作为主键的时候,要选择最常作为访问条件的列作为 主键,提?查询的效率。另外,还需要注意,InnoDB 表的普通索引都会保存主键的键值,所以主键要尽可能选择 较短的数据类型,可以有效地减少索引的磁盘占?,提?索引的缓存效果。

3 BTREE索引与HASH索引
MEMORY存储引擎的表可以选择使?BTREE索引或者HASH索引,两种不同类型的索引各有其不同的适?范围。HASH索引有?些重要的特征需要在使?的时候特别 注意,如下所?。
只?于使?=或<=>操作符的等式?较。优化器不能使?HASH索引来加速ORDER   BY操作。

MySQL 不能确定在两个值之间?约有多少?。如果将?个 MyISAM 表改为 HASH索引的MEMORY表,会影 响?些查询的执?效率。只能使?整个关键字来搜索??。

 ?对于BTREE索引,当使?>、<、>=、<=、BETWEEN、!=或者<>,或者LIKE ‘pattern‘       (其中‘pattern‘不以通配符开始)操作符时,都可以使?相关列上的索引。
下列范围查询适?于BTREE索引和HASH索引:

SELECT * FROM t1 WHERE key_col = 1 OR key_col IN (15,18,20);
下列范围查询只适?于BTREE索引:
SELECT * FROM t1 WHERE key_col > 1 AND key_col < 10;
SELECT * FROM t1 WHERE key_col LIKE ‘ab%‘ OR key_col BETWEEN ‘lisa‘ AND ‘simon‘;
例如,创建?个和city表完全相同的MEMORY存储引擎的表city_memory:
mysql> CREATE TABLE city_memory (
-> city_id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
-> city VARCHAR(50) NOT NULL,
-> country_id SMALLINT UNSIGNED NOT NULL,
-> last_update TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE  CURRENT_ TIMESTAMP,
-> PRIMARY KEY (city_id),
-> KEY idx_fk_country_id (country_id)
->  )ENGINE=Memory  DEFAULT CHARSET=utf8;
Query OK, 0 rows affected (0.03 sec)
mysql> insert into city_memory select * from city; Query OK, 600 rows affected (0.00 sec)
Records: 600 Duplicates: 0 Warnings: 0
当对索引字段进?范围查询的时候,只有BTREE索引可以通过索引访问:
mysql> explain SELECT * FROM city WHERE country_id > 1 and country_id < 10 G
*************************** 1. row *************************** id: 1
select_type: SIMPLE

table: city type: range
possible_keys: idx_fk_country_id key: idx_fk_country_id
key_len: 2 ref: NULL rows: 24
Extra: Using where
1 row in set (0.00 sec)
?HASH索引实际上是全表扫描的:
mysql> explain SELECT * FROM city_memory WHERE country_id > 1 and country_id < 10 G
*************************** 1. row *************************** id: 1
select_type: SIMPLE table: city_memory type: ALL
possible_keys: idx_fk_country_id key: NULL
key_len: NULL ref: NULL rows: 600
Extra: Using where
1 row in set (0.00 sec)
了解了 BTREE 索引和 HASH 索引不同后,当使? MEMORY 表时,如果是默认 创建的HASH  索引,就要注意  SQL  语句的编写,确保可以使?上索引,如果?定要使
?范围查询,那么在创建索引时,就应该选择创建成BTREE索引。 

 

以上是关于MySQL数据库索引的主要内容,如果未能解决你的问题,请参考以下文章

mysql数据库怎么建索引?

mysql索引类型解释

mysql索引类型解释

mysql索引类型和索引方式

mysql索引类型都有哪些

mysql中,索引,主键,唯一索引,联合索引的区别是?对数据库的性能有啥影响?