【Mysql调优】(四) :索引

序言

     之前我一直认为对于Java开发而言,只要学会SQL的增删改查(包括复杂查询)语句就可以了,然而在一次对于几千万的数据进行复杂查询时,数据库居然崩溃了。当时领导催得紧,没办法自己乱操作一顿,结果可想而知,电脑死机了。当时唯一能庆幸的是服务器是UAT,最后只能去问百度爸爸了,经过多方面的百度我知道了还有SQL调优这个骚操作,接着又了解了 索引<一数据引擎<一B+Treem<一.......<一二叉树,当时我是从左往右学习,走了 很多弯路,当时真想一句妈卖批。

一、索引的优点和缺点以及使用原则

1、优点

  • 类似于大学图书馆建书目索引,提高数据检索的效率,降低数据库的IO成本
  • 通过索引列对数据进行排序,降低数据排序的成本,降低了CPU的消耗

2、缺点

  •   虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行INSERT、UPDATE和DELETE。因为更新表时,MySQL不仅要保存数据,还要保存一下索引文件每次更新添加了索引列的字段,都会调整因为更新所带来的键值变化后的索引信息。
  • 索引只是提高效率的一个因素,如果你的MySQL有大数据量的表,就需要花时间研究建立最优秀的索引,或优化查询语句

3、使用原则

         应该在这些列上创建索引

  • 在经常需要搜索的列上,可以加快搜索的速度;
  • 在作为主键的列上,强制该列的唯一性和组织表中数据的排列结构;
  • 在经常用在连接的列上,这些列主要是一些外键,可以加快连接的速度;
  • 在经常需要根据范围进行搜索的列上创建索引,因为索引已经排序,其指定的范围是连续的;
  • 在经常需要排序的列上创建索引,因为索引已经排序,这样查询可以利用索引的排序,加快排序查询时间;
  • 在经常使用在 WHERE 子句中的列上面创建索引,加快条件的判断速度。

        不应该在这些列上创建索引

  • 对于那些在查询中很少使用或者参考的列不应该创建索引。这是因为,既然这些列很少使用到,因此有索引或者无索引,并不能提高查询速度。相反,由于增加了索引,反而降低了系统的维护速度和增大了空间需求。
  • 对于频繁更新的字段不适合创建索引(因为每次更新都需要更新索引),对频繁作为查询条件的字段应该创建索引
  • 对于那些只有很少数据值的列也不应该增加索引。这是因为,由于这些列的取值很少,例如人事表的性别列,在查询的结果中,结果集的数据行占了表中数据行的很大比例,即需要在表中搜索的数据行的比例很大。增加索引,并不能明显加快检索速度。
  • 对于那些定义为 text, image 和 bit 数据类型的列不应该增加索引。这是因为,这些列的数据量要么相当大,要么取值很少。
  • 当修改性能远远大于检索性能时,不应该创建索引。这是因为,修改性能和检索性能是互相矛盾的。当增加索引时,会提高检索性能,但是会降低修改性能(每次修改都会重新维护索引)。当减少索引时,会提高修改性能,降低检索性能

     通过上面说的,我们应该可以知道,并不是每个字段度设置索引就好,也不是索引越多越好,而是需要自己合理的使用。

 

二、索引分类

1、主键索引

           主键是一种唯一性索引,但它必须指定为“PRIMARY KEY”。如果你曾经用过AUTO_INCREMENT类型的列,你可能已经熟悉主键之类的概念了。主键一般在创建表的时候指定,例如

CREATE TABLE table_name ( [...], PRIMARY KEY (columnName)); 

但是,我们也可以通过修改表的方式加入主键,例如

ALTER TABLE table_name ADD PRIMARY KEY (columnName);

2、普通索引

  普通索引(由关键字KEY或INDEX定义的索引)的唯一任务是加快对数据的访问速度。因此,应该只为那些最经常出现在查询条件(WHERE  column=)或排序条件(ORDERBY column)中的数据列创建索引。只要有可能,就应该选择一个数据最整齐、最紧凑的数据列(如一个整数类型的数据列)来创建索引。

  • 建表同时创建索引
CREATE TABLE table_name ( [...], PRIMARY KEY (name),INDEX index_columnName (columnName)); 
  • 直接创建索引
CREATE INDEX index_columnName ON table_name(columnName)
  • 修改表结构的方式添加索引
ALTER TABLE table_name ADD INDEX index_columnName(columnName)
  • 删除索引
DROP INDEX index_columnName ON table_name

直观示例:

 

mysql> show index from emp;
+-------+------------+----------+--------------+-------------+-----------+-------------+------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Index_type | 
+-------+------------+----------+--------------+-------------+-----------+-------------+------------+
| emp   |          0 | PRIMARY  |            1 | id          | A         |      498341 | BTREE      | 
1 row in set (0.00 sec)

mysql> explain select *  from  emp where deptno=110;
+----+-------------+-------+------+---------------+------+---------+------+--------+-------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows   | Extra       |
+----+-------------+-------+------+---------------+------+---------+------+--------+-------------+
|  1 | SIMPLE      | emp   | ALL  | NULL          | NULL | NULL    | NULL | 498341 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+--------+-------------+
1 row in set (0.00 sec)

mysql> create index index_deptno on emp(deptno);
Query OK, 0 rows affected (1.61 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> show index from emp;
+-------+------------+--------------+--------------+-------------+-----------+-------------+------------+
| Table | Non_unique | Key_name     | Seq_in_index | Column_name | Collation | Cardinality | Index_type | 
+-------+------------+--------------+--------------+-------------+-----------+-------------+------------+
| emp   |          0 | PRIMARY      |            1 | id          | A         |      498341 | BTREE      | 
| emp   |          1 | index_deptno |            1 | deptno      | A         |          18 | BTREE      |
+-------+------------+--------------+--------------+-------------+-----------+-------------+------------+
2 rows in set (0.00 sec)
mysql
> explain select * from emp where deptno=110; +----+-------------+-------+------+---------------+--------------+---------+-------+------+-------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+---------------+--------------+---------+-------+------+-------+ | 1 | SIMPLE | emp | ref | index_deptno | index_deptno | 3 | const | 1 | NULL | +----+-------------+-------+------+---------------+--------------+---------+-------+------+-------+ 1 row in set (0.05 sec) mysql> DROP INDEX index_deptno ON emp; Query OK, 0 rows affected (0.32 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> show index from emp; +-------+------------+----------+--------------+-------------+-----------+-------------+------------+ | Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Index_type | +-------+------------+----------+--------------+-------------+-----------+-------------+------------+ | emp | 0 | PRIMARY | 1 | id | A | 498341 | BTREE | +-------+------------+----------+--------------+-------------+-----------+-------------+------------+ 1 row in set (0.00 sec) mysql> show index from emp; +-------+------------+----------+--------------+-------------+-----------+-------------+------------+ | Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Index_type | +-------+------------+----------+--------------+-------------+-----------+-------------+------------+ | emp | 0 | PRIMARY | 1 | id | A | 498341 | BTREE | +-------+------------+----------+--------------+-------------+-----------+-------------+------------+ 1 row in set (0.00 sec) mysql> ALTER TABLE emp ADD INDEX index_deptno(deptno); Query OK, 0 rows affected (1.97 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> show index from emp; +-------+------------+--------------+--------------+-------------+-----------+-------------+------------+ | Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Index_type | +-------+------------+--------------+--------------+-------------+-----------+-------------+------------+ | emp | 0 | PRIMARY | 1 | id | A | 498341 | BTREE | | emp | 1 | index_deptno | 1 | deptno | A | 18 | BTREE | +-------+------------+--------------+--------------+-------------+-----------+-------------+------------+ 2 rows in set (0.00 sec)

 

3、唯一索引

    与普通索引类似,不同的就是:索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须唯一。它有以下几种创建方式:

  • 建表同时创建索引
CREATE TABLE table_name ( [...], PRIMARY KEY (name),  UNIQUE index_columnName (columnName)); 
  • 创建唯一索引
CREATE UNIQUE INDEX index_columnName ON table_name(columnName);
  • 修改表结构的方式添加索引
ALTER TABLE table_name ADD UNIQUE index_columnName(columnName);
  • 删除索引与直观示例

        与普通索引类似

4、复合索引

    复合索引指多个字段上创建的索引,只有在查询条件中使用了创建索引时的第一个字段,索引才会被使用。使用复合索引时遵循最左前缀集合

  • 建表同时创建索引
CREATE TABLE table_name ( [...], PRIMARY KEY (name),INDEX index_columnName (columnName1,columnName2)); 
  • 接创建索引
CREATE UNIQUE INDEX index_columnName ON table_name(columnName1,columnName2);

与普通索引用法类推

5、全文索引

你可能感兴趣的:(【Mysql调优】(四) :索引)