zoukankan      html  css  js  c++  java
  • 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索引。 

  • 相关阅读:
    55、分页查询employees表,每5行一页,返回第2页的数据
    54、查找排除当前最大、最小salary之后的员工的平均工资avg_salary
    53、按照分组拼接字段
    52、获取Employees中的first_name
    51、查找字符串'10,A,B' 中逗号','出现的次数cnt
    图片素材
    软件下载
    一款高效卸载软件
    《单独.17 人的困境》(摘抄)
    Markdown的简单使用
  • 原文地址:https://www.cnblogs.com/guangxiang/p/11847048.html
Copyright © 2011-2022 走看看