MySQL索引

1.真的需要索引嗎?

MySQL索引的建立對於MySQL的高效運行是很重要的,索引可以大大提高MySQL的檢索速度。

打個比方,如果合理的設計且使用索引的MySQL是一輛蘭博基尼的話,那麼沒有設計和使用索引的MySQL就是一個人力三輪車。

拿漢語字典的目錄頁(索引)打比方,我們可以按拼音、筆畫、偏旁部首等排序的目錄(索引)快速查找到需要的字。

索引分單列索引和組合索引。單列索引,即一個索引只包含單個列,一個表可以有多個單列索引,但這不是組合索引。組合索引,即一個索引包含多個列。

上面都在說使用索引的好處,但過多的使用索引將會造成濫用。因此索引也會有它的缺點:雖然索引大大提高了查詢速度,同時卻會降低更新表的速度,如對錶進行INSERT、UPDATEDELETE。因爲更新表時,MySQL不僅要保存數據,還要保存一下索引文件。
建立索引會佔用磁盤空間的索引文件。

2.什麼是索引

索引(在 MySQL 中也叫“鍵key”)是存儲引擎快速找到記錄的一種數據結構
——《高性能MySQL》

我們需要知道索引其實是一種數據結構,其功能是幫助我們快速匹配查找到需要的數據行,是數據庫性能優化最常用的工具之一。其作用相當於超市裏的導購員、書本里的目錄。

3.測試表

本篇文章,我們將從索引基礎開始,介紹什麼是索引以及索引的幾種類型,然後學習如何創建索引以及索引設計的基本原則。
本篇文章中用於測試索引創建的user表的結構如下:

DROP TABLE IF EXISTS `user`;
CREATE TABLE `user`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `gender` int(1) NOT NULL,
  `age` int(3) NOT NULL,
  `status` int(1) NOT NULL,
  `remark` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;

4.索引類型

查看索引詳情

SHOW INDEX FROM table_name;

例如:

mysql> SHOW INDEX FROM user;
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| user  |          0 | PRIMARY  |            1 | id          | A         |           0 | NULL     | NULL   |      | BTREE      |         |               |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
1 row in set (0.03 sec)

4.1.主鍵索引

它是一種特殊的唯一索引,不允許有空值。一般是在建表的時候同時創建主鍵索引。

mysql> SHOW INDEX FROM user;
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| user  |          0 | PRIMARY  |            1 | id          | A         |           0 | NULL     | NULL   |      | BTREE      |         |               |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
1 row in set (0.03 sec)

注意:一個表只能有一個主鍵

4.2.唯一索引

唯一索引列的值必須唯一,但允許有空值。如果是組合索引,則列值的組合必須唯一。
創建唯一索引:

ALTER TABLE table_name ADD UNIQUE (column);

示例:

mysql> alter table user add unique(name);
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0
mysql> SHOW INDEX FROM user;
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| user  |          0 | PRIMARY  |            1 | id          | A         |           0 | NULL     | NULL   |      | BTREE      |         |               |
| user  |          0 | name     |            1 | name        | A         |           0 | NULL     | NULL   |      | BTREE      |         |               |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
2 rows in set (0.03 sec)

創建唯一組合索引:

ALTER TABLE table_name ADD UNIQUE (column1,column2);

示例:

mysql> ALTER TABLE user ADD UNIQUE unique_name_age (name,age);
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0
mysql> SHOW INDEX FROM user;
+-------+------------+-----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name        | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+-----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| user  |          0 | PRIMARY         |            1 | id          | A         |           0 | NULL     | NULL   |      | BTREE      |         |               |
| user  |          0 | name            |            1 | name        | A         |           0 | NULL     | NULL   |      | BTREE      |         |               |
| user  |          0 | unique_name_age |            1 | name        | A         |           0 | NULL     | NULL   |      | BTREE      |         |               |
| user  |          0 | unique_name_age |            2 | age         | A         |           0 | NULL     | NULL   |      | BTREE      |         |               |
+-------+------------+-----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
4 rows in set (0.03 sec)

4.3.普通索引

最基本的索引,它沒有任何限制。

創建普通索引:

ALTER TABLE table_name ADD INDEX index_name (column);

示例:

mysql> alter table user add index index_name(name);
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0
mysql> SHOW INDEX FROM user;
+-------+------------+-----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name        | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+-----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| user  |          0 | PRIMARY         |            1 | id          | A         |           0 | NULL     | NULL   |      | BTREE      |         |               |
| user  |          0 | name            |            1 | name        | A         |           0 | NULL     | NULL   |      | BTREE      |         |               |
| user  |          0 | unique_name_age |            1 | name        | A         |           0 | NULL     | NULL   |      | BTREE      |         |               |
| user  |          0 | unique_name_age |            2 | age         | A         |           0 | NULL     | NULL   |      | BTREE      |         |               |
| user  |          1 | index_name      |            1 | name        | A         |           0 | NULL     | NULL   |      | BTREE      |         |               |
+-------+------------+-----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
5 rows in set (0.03 sec)

4.4.組合索引

組合索引,即一個索引包含多個列。多用於避免回表查詢。
創建組合索引:

ALTER TABLE table_name ADD INDEX index_name(column1, column2, column3);

示例:

mysql> alter table user add index index_name_age(name,age);
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0
mysql> SHOW INDEX FROM user;
+-------+------------+-----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name        | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+-----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| user  |          0 | PRIMARY         |            1 | id          | A         |           0 | NULL     | NULL   |      | BTREE      |         |               |
| user  |          0 | name            |            1 | name        | A         |           0 | NULL     | NULL   |      | BTREE      |         |               |
| user  |          0 | unique_name_age |            1 | name        | A         |           0 | NULL     | NULL   |      | BTREE      |         |               |
| user  |          0 | unique_name_age |            2 | age         | A         |           0 | NULL     | NULL   |      | BTREE      |         |               |
| user  |          1 | index_name      |            1 | name        | A         |           0 | NULL     | NULL   |      | BTREE      |         |               |
| user  |          1 | index_name_age  |            1 | name        | A         |           0 | NULL     | NULL   |      | BTREE      |         |               |
| user  |          1 | index_name_age  |            2 | age         | A         |           0 | NULL     | NULL   |      | BTREE      |         |               |
+-------+------------+-----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
7 rows in set (0.05 sec)

4.5.全文索引

全文索引(也稱全文檢索)是目前搜索引擎使用的一種關鍵技術。
創建全文索引

ALTER TABLE table_name ADD FULLTEXT (column);

示例:

mysql> ALTER TABLE user ADD FULLTEXT (remark);
Database changed
Records: 0  Duplicates: 0  Warnings: 0
mysql> SHOW INDEX FROM user;
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| user  |          0 | PRIMARY  |            1 | id          | A         |           0 | NULL     | NULL   |      | BTREE      |         |               |
| user  |          1 | remark   |            1 | remark      | NULL      | NULL        | NULL     | NULL   | YES  | FULLTEXT   |         |               |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
2 rows in set

備註: 如果是InnoDB,改爲MyISAM,InnoDB不支持FULLTEXT類型的索引

5.刪除索引

索引一經創建不能修改,如果要修改索引,只能刪除重建。
刪除索引:

DROP INDEX index_name ON table_name;

6.索引設計的原則

1.適合索引的列是出現在where子句中的列,或者連接子句中指定的列
2.基數較小的類,索引效果較差,沒有必要在此列建立索引
3.使用短索引,如果對長字符串列進行索引,應該指定一個前綴長度,這樣能夠節省大量索引空間

CREATE INDEX indexName ON mytable(username(length)); 
如果是CHAR,VARCHAR類型,length可以小於字段實際長度;如果是BLOB和TEXT類型,必須指定 length。

4.不要過度索引。索引需要額外的磁盤空間,並降低寫操作的性能。在修改表內容的時候,索引會進行更新甚至重構,索引列越多,這個時間就會越長。所以只保持需要的索引有利於查詢即可。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章