1. 程式人生 > >非聚集索引和聚集索引

非聚集索引和聚集索引

每次 方式 possible .com 表數據 alt ons row span

一.非聚集索引(MyISAM的索引方式):

使用B+Tree作為索引結構,葉節點的data域存放的是數據記錄的地址.主鍵索引圖:

技術分享圖片

輔助索引圖:

技術分享圖片

主鍵索引和輔助索引沒有本質上的區別,data域都保存的是數據行的地址.

二.聚集索引(InnoDB的索引方式):

InnoDB的數據文件本身就是索引文件。在InnoDB中,表數據文件本身就是按B+Tree組織的一個索引結構,這棵樹的葉節點data域保存了完整的數據記錄。這個索引的key是數據表的主鍵,因此InnoDB表數據文件本身就是主索引。

主鍵索引圖:

技術分享圖片

輔助索引:

InnoDB的輔助索引data域存儲相應記錄主鍵的值而不是地址。換句話說,InnoDB的所有輔助索引都引用主鍵作為data域.

技術分享圖片

ps:

1.如果innodb表沒有主鍵索引,innodb會自動找一個類似於此的唯一非空列,如果找不到,會增加一個隱藏列來做主索引.

2.Innodb中的每張表都會有一個聚集索引,而聚集索引又是以物理磁盤順序來存儲的,自增主鍵會把數據自動向後插入,避免了插入過程中的聚集索引排序問題。

三.覆蓋索引

覆蓋索引指的是數據的讀取不必經過數據行,而是直接從索引中讀取.這是mysql而言,是效率最好的讀取方式.

對於覆蓋索引而言,myisam和innodb有截然不同的表現(非聚集索引和聚集索引)

建立表:

CREATE TABLE `test` (
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `time` int(11) DEFAULT NULL,
    PRIMARY KEY (`id`),
    KEY `time` (`time`)
) ENGINE=MyISAM;

  

插入數據:

insert into test(time) values(1);
insert into test(time) values(2);

  

我們來查詢一條數據,看看mysql解釋器表現:

mysql> explain select id from test where time=1;
+----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+
| id | select_type | table | type  | possible_keys | key     | key_len | ref   | rows | Extra |
+----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+
|  1 | SIMPLE      | test  | const | PRIMARY       | PRIMARY | 4       | const |    1 |       |
+----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+

  

註意Extra列,沒有出現using index;也就是沒有使用覆蓋索引;這很好理解,因為非聚集索引,該查詢先查詢了time索引(或key cache),找到對應記錄的地址,然後去數據行找數據了;mysql每次查詢只能用到一個索引.

如果是以下語句,就用到了覆蓋索引:

mysql> explain select time from test where time=1;
+----+-------------+-------+------+---------------+------+---------+-------+------+--------------------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref   | rows | Extra                    |
+----+-------------+-------+------+---------------+------+---------+-------+------+--------------------------+
|  1 | SIMPLE      | test  | ref  | time          | time | 5       | const |    1 | Using where; Using index |
+----+-------------+-------+------+---------------+------+---------+-------+------+--------------------------+

  

用到了time索引,只要求返回time列,不必去數據行找數據;直接從索引中找到數據返回;

現在我們將該表轉為innodb,看看innodb的表現:

mysql> explain select id from test where time=1;
+----+-------------+-------+------+---------------+------+---------+-------+------+--------------------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref   | rows | Extra                    |
+----+-------------+-------+------+---------------+------+---------+-------+------+--------------------------+
|  1 | SIMPLE      | test  | ref  | time          | time | 5       | const |    1 | Using where; Using index |
+----+-------------+-------+------+---------------+------+---------+-------+------+--------------------------+

  

用到了覆蓋索引.

mysql> explain select time from test where time=1;
+----+-------------+-------+------+---------------+------+---------+-------+------+--------------------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref   | rows | Extra                    |
+----+-------------+-------+------+---------------+------+---------+-------+------+--------------------------+
|  1 | SIMPLE      | test  | ref  | time          | time | 5       | const |    1 | Using where; Using index |
+----+-------------+-------+------+---------------+------+---------+-------+------+--------------------------+

  

四.文件排序和索引掃描排序

非聚集索引和聚集索引