什么是數據庫索引?
索引用於快速找出在某個列中有一特定值的行,如果不使用索引MySQL必須從第l條
記錄開始讀完整個表,直到找出相關的行.表越大,查詢數據所花費的時間越多,如果表中查詢的列有一個索引,MySQL能快速到達某個位置去搜尋數據文件,而不必查看所有數據.
索引是一個單獨的、存儲在磁盤上的數據庫結構,它們包含着對數據表里所有記錄的引用指針.使用索引用於快速找出在某個或多個列中有一特定值的行,所有MySQL列類型都可以被索引,對相關列使用索引是提高查詢操作速度的最佳途徑.
這里打個比方:比如我們要查找num=1000
,如果沒有索引,那么MySQL將會遍歷整個表,直到找到1000這一行為止
.如果有索引的情況下,當我們查找num時,MySQL不需要任何遍歷,直接在索引里找到數據的位置,這樣一來提高了數據庫的查詢效率.
索引與存儲引擎?
索引是在存儲引擎中實現的,因此每種存儲引擎的索引都不一定完全相同,並且每種存諸引擎也不一定支持所有索引類型.根據存儲引擎定義每個表的最大索引數和最大索引長度,存儲引擎支持每個表至少16個
索引,總索引長度至少為256字節
.大多數存儲引擎有更高的限制,MySQL中索引的存儲類型有兩種:1.BTREE和HASH,具體和表的存儲引擎相關
,2.MyISAM和InnoDB存儲引擎只支持BTREE索引
,3.MEMORY/HEAP存儲引擎可以支持HASH和BTREE索引
.
MySQL索引的優點:
● 通過創建唯一索引,可以保證數據庫表中每一行數據的唯一性
● 可以大大加快數據的查詢速度
● 在實現數據的參考完整性方面,可以加速表和表之間的連接
● 使用分組和排序子句進行數據查詢時,也可以顯著減少查詢中分組和排序的時間
MySQL索引的缺點:
● 維護索引要花費大量時間,並且隨着數據量的增加所耗費的時間也會增加
● 索引占用磁盤空間,每一個索引要占一定得物理空間,如果有大量索引,索引文件可能比數據文件更快達到最大文件尺寸
● 當對數據進行增刪改查時,索引也需要動態調整,大大降低了數據的可維護性
MySQL索引的設計原則:
● 索引並非越多越好,一個表中如有大量的索引,不僅占用磁盤空間,而且會影響語句執行效率
● 避免對經常更新的表進行過多的索引,並且索引中的列盡可能少
● 對經常用於查詢的字段應該創建索引,但要避免添加不必要的字段
● 數據量小的表最好不要使用索引,如果添加索引可能非但達不到好的效果,反而適得其反
● 在條件表達式中經常用到的不同值較多的列上建立索引,在不同值很少的列上不要建立索引
● 當唯一性是某種數據本身的特征時,指定唯一索引,可以提高數據查詢效率
● 在頻繁進行排序或分組(group by或order by操作)的列上建立索引
MySQL索引的分類有哪些?
1.普通索引:MySQL中的基本索引類型,允許在定義索引的列中插入重復值和空值.
2.唯一索引:索引列的值必須唯一,但允許有空值.如果是組合索引,則列值的組合必須唯一.
3.主鍵索引:一種特殊的唯一索引,不允許有空值.
4.單列索引:即一個索引只包含單個列,一個表可以有多個單列索引.
5.組合索引:指在表的多個字段組合上創建的索引,使用組合索引時遵循最左前綴集合.
6.全文索引:允許在這些索引列中插入重復值和空值,只有MyISAM存儲引擎支持全文索引.
7.空間索引:對空間數據類型的字段建立的索引,空間索引只能在存儲引擎為MyISAM的表中創建.
MariaDB支持多種方法在單個或多個列上創建索引,在創建表的定義語句create table
中指定索引列,使用alter table
語句在存在的表上創建索引,或使用create index
語句在已存在表上添加索引.
以上的知識點就是索引章節的全部內容啦,其實索引的實踐環節還是很簡單的,只需要了解幾個命令就行啦,接下來我們來看一下索引的具體使用過程吧.
MariaDB 創建索引
使用CREATE TABLE
創建表時,除了可以定義列的數據類型,還可以定義主鍵約束、外鍵約束或者唯一性約束,而不論創建那種約束,在定義約束的同時相當於在指定列上創建了一個索引。創建表時創建索引的基本語法格式如下:
MariaDB [lyshark]> create table table_name [col_name data_type]
[unique | fulltext | spatial]
[index | key][index_name] (col_name [length])
[ASC | DESC]
#----------------------------------------------------------------------------------------
#[參數解釋]
unique | fulltext | spatial #可選參數,分別表示唯一索引,全文索引,空間索引
index | key #兩者作用相同,用來指定創建索引
col_name #需要創建索引的字段列,此列必須從數據表中定義的列中選擇
length #可選參數,表示索引長度,只用字符串類型才能指定索引長度
ASC | DESC #指定升序或者降序的索引值存儲
◆創建普通索引◆
創建最基本的索引類型,沒有唯一性之類的限制,其作用只是加對快數據的訪問速度.
1.創建book
表的同時,在year_public
字段上建立普通索引,SQL語句如下:
MariaDB [lyshark]> create table book
-> (
-> bookid int not null,
-> bookname varchar(255) not null,
-> authors varchar(255) not null,
-> info varchar(255) null,
-> comment varchar(255) null,
-> year_public year not null,
-> index(year_public)
-> );
Query OK, 0 rows affected (0.03 sec)
MariaDB [lyshark]> desc book;
+-------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------------+--------------+------+-----+---------+-------+
| bookid | int(11) | NO | | NULL | |
| bookname | varchar(255) | NO | | NULL | |
| authors | varchar(255) | NO | | NULL | |
| info | varchar(255) | YES | | NULL | |
| comment | varchar(255) | YES | | NULL | |
| year_public | year(4) | NO | MUL | NULL | |
+-------------+--------------+------+-----+---------+-------+
6 rows in set (0.00 sec)
2.執行完語句后,我們可以使用show create table
查看表結構:
MariaDB [lyshark]> show create table book \G;
*************************** 1. row ***************************
Table: book
Create Table: CREATE TABLE `book` (
`bookid` int(11) NOT NULL,
`bookname` varchar(255) NOT NULL,
`authors` varchar(255) NOT NULL,
`info` varchar(255) DEFAULT NULL,
`comment` varchar(255) DEFAULT NULL,
`year_public` year(4) NOT NULL, #成功建立了索引
KEY `year_public` (`year_public`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
1 row in set (0.00 sec)
3.使用explain
語句查看索引是否正在使用,SQL語句如下:
MariaDB [lyshark]> explain select * from book where year_public=990 \G;
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: book
type: ref
possible_keys: year_public
key: year_public
key_len: 1
ref: const
rows: 1
Extra: Using index condition
1 row in set (0.00 sec)
對以上EXPLAIN語句輸出結果的解釋:
●
select type
:指定所使用的SELECT查詢類型,這里值為SIMPLE
●table
:指定數據庫讀取的數據表的名字
●type
:指定了本數據表與其他數據表之間的關聯關系
●possible keys
:給出了MySQL在搜索數據記錄時可選用的各個索引
●key
行是MySQL實際選用的索引
●key len
:行給出索引按字節計算的長度,key len數值越小,表示越快
●ref
:行給出了關聯關系中另一個數據表里的數據列的名字
●rows
:行是MySQL在執行這個查詢時預計會從這個數據表里讀出的數據行的個數
●extra
:行提供了與關聯操作有關的信息
可以看到,possible keys
和key
的值都為year_public,說明查詢時使用了索引.
◆創建唯一索引◆
創建唯一索引的主要原因是減少查詢索引列操作的執行時間
,尤其是對比較龐大的數據表.它與前面的普通索引類似,不同的就是:索引列的值必須唯一,但允許有空值.如果是組合索引,則列值的組合必須唯一.
創建一個表table_1
,在表中的id
字段上使用unique
關鍵字創建唯一索引
MariaDB [lyshark]> create table table_1
-> (
-> id int not null,
-> name char(30) not null,
-> unique index UniqIdx(id)
-> );
Query OK, 0 rows affected (0.02 sec)
MariaDB [lyshark]> show create table table_1 \G;
*************************** 1. row ***************************
Table: table_1
Create Table: CREATE TABLE `table_1` (
`id` int(11) NOT NULL,
`name` char(30) NOT NULL,
UNIQUE KEY `UniqIdx` (`id`) #id字段已經成功建立了一個名為UniqIdx的唯一索引
) ENGINE=InnoDB DEFAULT CHARSET=latin1
1 row in set (0.00 sec)
◆創建單列索引◆
單列索引是在數據表中的某一個字段上創建的索引
,一個表中可以創建多個單列索引.前面兩個例子中創建的索引都為單列索引.
創建一個表table_2
,在表中的name字段
上創建單列索引.
MariaDB [lyshark]> create table table_2
-> (
-> id int not null,
-> name char(50) null,
-> index SingleIdx(name(20))
-> );
Query OK, 0 rows affected (0.03 sec)
MariaDB [lyshark]> show create table table_2 \G;
*************************** 1. row ***************************
Table: table_2
Create Table: CREATE TABLE `table_2` (
`id` int(11) NOT NULL,
`name` char(50) DEFAULT NULL,
KEY `SingleIdx` (`name`(20)) #name字段上已經成功建立了一個單列索引,名稱為SingleIdx
) ENGINE=InnoDB DEFAULT CHARSET=latin1
1 row in set (0.00 sec)
◆創建組和索引◆
組合索引就是在多個字段上創建一個索引.
1.首先創建table_3
表,在表中的id,name,age
字段上建立組合索引,SQL語句如下:
MariaDB [lyshark]> create table table_3
-> (
-> id int not null,
-> name char(30) not null,
-> age int not null,
-> info varchar(255),
-> INDEX MultiIdx(id,name,age)
-> );
Query OK, 0 rows affected (0.01 sec)
2.創建完成之后,我們來查看一下結果吧.
MariaDB [lyshark]> show create table table_3 \G
*************************** 1. row ***************************
Table: table_3
Create Table: CREATE TABLE `table_3` (
`id` int(11) NOT NULL,
`name` char(30) NOT NULL,
`age` int(11) NOT NULL,
`info` varchar(255) DEFAULT NULL,
KEY `MultiIdx` (`id`,`name`,`age`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
1 row in set (0.00 sec)
3.測試,在table_3
表中,差查詢id和name
字段,使用explain
語句查看索引的使用情況:
MariaDB [lyshark]> explain select * from table_3 where id=1 and name='lyshark' \G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: table_3
type: ref
possible_keys: MultiIdx
key: MultiIdx
key_len: 34
ref: const,const
rows: 1
Extra: Using index condition
1 row in set (0.07 sec)
◆創建全文索引◆
FULLTEXT(全文索引)可以用於全文搜索,全文索引適合用於大型數據集
.只有MyISAM存儲引擎支持
FULLTEXT索引,並且只為CHAR、VARCHAR和TEXT列
創建索引.索引總是對整個列進行,不支持局部(前綴)索引.
1.創建表table_4
在表中info字段
上建立一個全文索引,SQL語句如下:
MariaDB [lyshark]> create table table_4(
-> id int not null,
-> name char(40) not null,
-> age int not null,
-> info varchar(255),
-> fulltext index FullTxtIdx(info)
-> )engine=MyISAM;
Query OK, 0 rows affected (0.00 sec)
#注意:MySQL5.7默認存儲引擎室是InnoDB,在這里我們要改成MyISAM,不然索引會報錯
2.結果如下,這樣我們就創建了一個名為FullTxtIdx
的全文索引.
MariaDB [lyshark]> show create table table_4 \G
*************************** 1. row ***************************
Table: table_4
Create Table: CREATE TABLE `table_4` (
`id` int(11) NOT NULL,
`name` char(40) NOT NULL,
`age` int(11) NOT NULL,
`info` varchar(255) DEFAULT NULL,
FULLTEXT KEY `FullTxtIdx` (`info`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
1 row in set (0.00 sec)
◆創建空間索引◆
空間索引必須在MyISAM
類型的表中創建,且空間類型的字段必須為空.
1.創建一個表table_5
,在空間類型Geometry的字段
上創建空間索引,SQL語句如下:
MariaDB [lyshark]> create table table_5
-> (
-> g geometry not null,
-> spatial index spatIdx(g)
-> )engine=MyISAM;
Query OK, 0 rows affected (0.00 sec)
MariaDB [lyshark]> show create table table_5 \G;
*************************** 1. row ***************************
Table: table_5
Create Table: CREATE TABLE `table_5` (
`g` geometry NOT NULL,
SPATIAL KEY `spatIdx` (`g`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
1 row in set (0.00 sec)
可以看到,table_5表
的g字段
上創建了名稱為spatIdex
的空間索引,注意:創建時間指定空間類型字段值的非空約束,並且表的存儲引擎必須為MyISAM.
MariaDB 添加索引
在已經存在的表中創建索引,可以使用alter table
語句或者create index
語句,本節將介紹如何在一個已經存在的表上創建一個索引,首先先來看一下索引的添加語法,SQL語句如下:
alter table table_name add [unique | fulltext | spatial ]
[ index | key ] [ index_name ](col_name[length],.....)
[ asc |esc ]
#----------------------------------------------------------------------------------------
#[參數解釋]
unique | fulltext | spatial #可選參數,分別表示唯一索引,全文索引,空間索引
index | key #兩者作用相同,用來指定創建索引
col_name #需要創建索引的字段列,此列必須從數據表中定義的列中選擇
length #可選參數,表示索引長度,只用字符串類型才能指定索引長度
ASC | DESC #指定升序或者降序的索引值存儲
◆添加普通索引◆
在book表中bookname字段
上,將建立名為BKNameIdx的普通索引
.
1.首先添加索引前,使用show index語句
查看指定表中創建的索引
MariaDB [lyshark]> show index from book \G;
*************************** 1. row ***************************
Table: book
Non_unique: 1
Key_name: year_public
Seq_in_index: 1
Column_name: year_public
Collation: A
Cardinality: 0
Sub_part: NULL
Packed: NULL
Null:
Index_type: BTREE
Comment:
Index_comment:
1 row in set (0.00 sec)
對以上語句輸出結果的解釋:
●
Table
:表示創建索引的表
●Non unique
:表示索引非唯一,1代表是非唯一索引,0代表唯一索引
●Key name
:表示索引的名稱
●Seq in index
:表示該字段在索引中的位置,單列索引該值為1,組合索引為每個字段在索引定義中的順序
●Column name
:表示定義索引的列字段
●Sub part
:表示索引的長度
●Null
:表示該字段是否能為空值
●Index type
:表示索弓引類型
可以看到,book表中已經存在了一個索引,即前面已經定義的名稱為year publication索引
,該索引為非唯一索引.
2.使用alter table
在bookname字段
上添加索引,SQL語句如下:
MariaDB [lyshark]> alter table book add index BKNameIdx(bookname(30));
Query OK, 0 rows affected (0.02 sec)
Records: 0 Duplicates: 0 Warnings: 0
3.使用show index
語句查看表中索引:
MariaDB [lyshark]> show index from book \G;
*************************** 1. row ***************************
Table: book
Non_unique: 1
Key_name: year_public
Seq_in_index: 1
Column_name: year_public
Collation: A
Cardinality: 0
Sub_part: NULL
Packed: NULL
Null:
Index_type: BTREE
Comment:
Index_comment:
*************************** 2. row ***************************
Table: book
Non_unique: 1
Key_name: BKNameIdx
Seq_in_index: 1
Column_name: bookname
Collation: A
Cardinality: 0
Sub_part: 30
Packed: NULL
Null:
Index_type: BTREE
Comment:
Index_comment:
2 rows in set (0.00 sec)
可以看到表中有兩個索引,一個通過alter table 語句
添加的名稱為BKNameIdx的索引
,該索引為非唯一索引,長度為30
.
◆添加唯一索引◆
在book表
的bookId字段
上建立名稱為UniqidIdx的唯一索引
,SQL語句如下:
MariaDB [lyshark]> alter table book add unique index UniqidIdx(bookId);
Query OK, 0 rows affected (0.05 sec)
Records: 0 Duplicates: 0 Warnings: 0
MariaDB [lyshark]> show index from book \G
*************************** 1. row ***************************
Table: book
Non_unique: 0
Key_name: UniqidIdx #此處為創建的唯一索引。
Seq_in_index: 1
Column_name: bookid
Collation: A
Cardinality: 0
Sub_part: NULL
Packed: NULL
Null:
Index_type: BTREE
Comment:
Index_comment:
可以看到,Non_unique屬性為0
,表示名稱為UniqidIdx的索引為唯一性索引
,創建唯一索引成功.
◆添加單列索引◆
在book表
的comment字段
建立單列索引,SQL語句如下:
MariaDB [lyshark]> alter table book add index BkcmtIdx(comment(50));
Query OK, 0 rows affected (0.03 sec)
Records: 0 Duplicates: 0 Warnings: 0
MariaDB [lyshark]> show index from book \G;
*************************** 4. row ***************************
Table: book
Non_unique: 1
Key_name: BkcmtIdx
Seq_in_index: 1
Column_name: comment
Collation: A
Cardinality: 0
Sub_part: 50
Packed: NULL
Null: YES
Index_type: BTREE
Comment:
Index_comment:
4 rows in set (0.00 sec)
語句執行后,book表的comment字段
上建立了名稱為BkcmtIdx的索引
,長度為50
,查詢時只需要檢索前50個
字符.
◆添加組和索引◆
在book表
的authors和info字段
上建立組合索引,SQL語句如下:
MariaDB [lyshark]> alter table book add index BkAuAndInfoIdx(authors(30),info(50));
Query OK, 0 rows affected (0.03 sec)
Records: 0 Duplicates: 0 Warnings: 0
MariaDB [lyshark]> show index from book \G;
*************************** 5. row ***************************
Table: book
Non_unique: 1
Key_name: BkAuAndInfoIdx
Seq_in_index: 1
Column_name: authors
Collation: A
Cardinality: 0
Sub_part: 30
Packed: NULL
Null:
Index_type: BTREE
Comment:
Index_comment:
*************************** 6. row ***************************
Table: book
Non_unique: 1
Key_name: BkAuAndInfoIdx
Seq_in_index: 2
Column_name: info
Collation: A
Cardinality: 0
Sub_part: 50
Packed: NULL
Null: YES
Index_type: BTREE
Comment:
Index_comment:
6 rows in set (0.00 sec)
可以看到,名稱為BkAuAndInfoIdx索引
,有兩個字段組成authors字段長度為30
,在組合索引中序列為1
該字段不許為空NULL,info字段長度為50
,在組合索引中的序號為2,該字段可以為空值NULL.
◆添加全文索引◆
創建表table_6
在table_6表上使用alter table
創建全文索引.
1.首先創建表table_6
並指定存儲引擎為MyISAM
,SQL語句如下:
MariaDB [lyshark]> create table table_6
-> (
-> id int not null,
-> info char(255)
-> )engine=MyISAM;
Query OK, 0 rows affected (0.01 sec)
2.創建並查看全文索引:
MariaDB [lyshark]> alter table table_6 add fulltext index infoFTIdx(info);
Query OK, 0 rows affected (0.01 sec)
Records: 0 Duplicates: 0 Warnings: 0
MariaDB [lyshark]> show index from table_6 \G;
*************************** 1. row ***************************
Table: table_6
Non_unique: 1
Key_name: infoFTIdx
Seq_in_index: 1
Column_name: info
Collation: NULL
Cardinality: NULL
Sub_part: NULL
Packed: NULL
Null: YES
Index_type: FULLTEXT
Comment:
Index_comment:
1 row in set (0.01 sec)
以上可知,table_6表
中已經創建了名稱為infoFTIdx的索引
,該索引在info字段
上創建,類型為fulltext
,允許為空.
◆添加空間索引◆
創建表table_7
,在table_7的空間數據類型字段g
上創建名稱為spatIdx的空間索引
,SQL語句如下:
1.首先創建表結構.
MariaDB [lyshark]> create table table_7
-> (
-> g geometry not null
-> )engine=MyISAM;
Query OK, 0 rows affected (0.00 sec)
2.使用alter table
在table_7
上創建空間索引.
MariaDB [lyshark]> alter table table_7 add spatial index spatIdx(g);
Query OK, 0 rows affected (0.00 sec)
Records: 0 Duplicates: 0 Warnings: 0
MariaDB [lyshark]> show index from table_7 \G;
*************************** 1. row ***************************
Table: table_7
Non_unique: 1
Key_name: spatIdx #此處是空間索引的名稱
Seq_in_index: 1
Column_name: g
Collation: A
Cardinality: NULL
Sub_part: 32
Packed: NULL
Null:
Index_type: SPATIAL
Comment:
Index_comment:
1 row in set (0.00 sec)
## MariaDB 刪除索引
刪除索引可以使用alter table
語句,下面我們介紹它的刪除方法,例如:刪除book表
中名稱為UniqidIdx的唯一索引
,SQL語句如下:
1.首先查看一下名稱為UniqidIdx
的索引,輸入Show語句:
MariaDB [lyshark]> show create table book \G;
*************************** 1. row ***************************
Table: book
Create Table: CREATE TABLE `book` (
`bookid` int(11) NOT NULL,
`bookname` varchar(255) NOT NULL,
`authors` varchar(255) NOT NULL,
`info` varchar(255) DEFAULT NULL,
`comment` varchar(255) DEFAULT NULL,
`year_public` year(4) NOT NULL,
UNIQUE KEY `UniqidIdx` (`bookid`), #下一步我們刪除它
KEY `year_public` (`year_public`),
KEY `BKNameIdx` (`bookname`(30)),
KEY `BkcmtIdx` (`comment`(50)),
KEY `BkAuAndInfoIdx` (`authors`(30),`info`(50))
) ENGINE=InnoDB DEFAULT CHARSET=latin1
1 row in set (0.00 sec)
2.刪除UniqidIdx
唯一索引,SQL語句如下:
MariaDB [lyshark]> alter table book drop index UniqidIdx; #刪除語句
Query OK, 0 rows affected (0.02 sec)
Records: 0 Duplicates: 0 Warnings: 0
MariaDB [lyshark]> show create table book \G; #刪除成功了
*************************** 1. row ***************************
Table: book
Create Table: CREATE TABLE `book` (
`bookid` int(11) NOT NULL,
`bookname` varchar(255) NOT NULL,
`authors` varchar(255) NOT NULL,
`info` varchar(255) DEFAULT NULL,
`comment` varchar(255) DEFAULT NULL,
`year_public` year(4) NOT NULL,
KEY `year_public` (`year_public`),
KEY `BKNameIdx` (`bookname`(30)),
KEY `BkcmtIdx` (`comment`(50)),
KEY `BkAuAndInfoIdx` (`authors`(30),`info`(50))
) ENGINE=InnoDB DEFAULT CHARSET=latin1
1 row in set (0.00 sec)
參考文獻:mysql5.7從入門到精通