Mysql之索引介紹
索引用於快速找出某個列中有一特定值的行。
不使用索引,MySql必須從第一條記錄開始讀完整個表,直到找出相關的行。表越大,查詢數據所花費的時間越多。
如果表中查詢的列有一個索引,Mysql能快速到達一個位置去搜索數據文件,而不必查看所有數據。
簡介:
索引是對數據庫表中一列或多列的值進行排序的一種結構,使用索引可以提高數據庫中特定數據的查詢速度。
索引是一個單獨的、存儲在磁盤上的數據庫結構,他們包含著對數據表裏所有記錄的引用指針。
使用索引用於快速找出某個或者多個列中有一特定值的行,所有Mysql列類型都可以被索引,對相關列使用索引是提高查詢操作速度的最佳途徑。
例如:數據庫中有2萬條記錄,現在要執行這樣一個查詢:
select * from table where num=10000
如果沒有索引,必須遍歷整個表,直到num等於10000的這一行被找到為止。
如果在num列上創建索引,MySql不需要任何掃描,直接在索引裏面找到10000,就可以得知這一行的位置。
索引是存儲引擎實現的,因此,每種存儲引擎的索引都不一定完全相同,並且每種存儲引擎也不一定支持所有索引類型。
根據存儲引擎定義每個表的最大索引數和最大索引長度。所有存儲引擎支持每個表至少16個索引,總索引長度至少為256字節。大多數存儲引擎有更高的限制。
MySql中索引的存儲類型有兩種:BTREE和HASH,具體和表的存儲引擎相關;MyISAM和InnoDB存儲引擎都支持BTREE索引;MEMORY/HEAP存儲引擎可以支持BTREE和HASH索引。
索引優點:
1、通過創建唯一索引,可以保證數據庫表中每一行數據的唯一性。
2、可以大大加快數據的查詢速度,這也是創建索引的最主要的原因。
3、在實現數據的參考完整性方面,可以加速表和表之間的鏈接。
4、在使用分組和排序子句進行數據查詢時,也可以顯著減少查詢中分組和排序的時間。
索引的缺點:
1、創建索引和維護索引要耗費時間,並且隨著數據量的增加所耗費的時間也會增加。
2、索引需要占據磁盤空間,除了數據表占數據空間之外,每一個索引還要占一定的物理空間,如果有大量的索引,索引文件可能比數據文件更快達到最大文件尺寸。
3、當對表中的數據進行增加、刪除和修改的時候,索引也要動態維護,這樣就降低了數據的維護速度。
MySql索引的分類:
1、普通索引和唯一索引
普通索引:Mysql中最基礎的索引類型,允許在定義索引的列中插入重復值和空值。
唯一索引:索引列的值必須唯一,但允許有空值。
如果是組合索引,則列值和組合必須唯一。主鍵索引是一種特殊唯一索引,不行允許有空值。
2、單列索引和組合索引
單列索引:一個索引只包含一個列,一個表也可以有多個單列索引。
組合索引:在表的多個字段組合上創建的索引,只有在查詢條件中使用了這些字段的左邊字段時,索引才會被使用。使用組合索引時遵循最左前綴集合。
3、全文索引
全文索引類型為FULLTEXT,在定義索引的列上支持值得全文查找,允許在這些索引列中插入重復值和空值。全文索引可以在CHAR,VARCHAR或者TEXT類型上創建。
只有MyISAM存儲引擎支持全文索引。
4、空間索引
空間索引是對空間數據類型的字段建立索引,Mysql中的空間數據有4中:GEOMETRY、POINT、LINESTRING和POLYGON。Mysl使用SPATIAL關鍵字進行擴展,使得能夠創建正規索引類似的語法創建空間索引。
創建空間索引的列,必須將其聲明為NOT NULL,空間索引只能在存儲引擎為MyISAM中創建。
索引表的設計原則:
1、索引表不是越多越好,一個表中如果有大量索引,不僅占用硬盤空間,還影響增刪改查等語句的性能,因為當表中的數據更改的同時,索引也會進行調整和更新。
2、避免經常更新的表進行過多的索引,並且索引表中的列盡可能少。而經常查詢的字段應該創建索引,但要避免添加不必要的字段。
3、數據量小的表最好不要使用索引。遍歷的時間短與索引的時候,並不會產生優化效果。
4、在條件表達式中經常用到的不同值較多的列上建立索引,在不同值少的列上不要建立索引。比如性別。
5、當唯一性是某種數據本身的特征時,指定唯一索引。使用唯一索引需要能確保定義的列的數據的完整性,以提高數據的查詢速度。
6、在頻繁進行排序或者分組(即進行group by 或order by操作)的列上建立索引,如果待排序的列有多個,可以在這些列上建立組合索引。
創建語法:
CREATE TABLE 指定索引列 ALTER TABLE 在存在的表上創建索引 CREATE INDEX 添加索引 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:需要創建索引的字段列,必須在表中定義的列 index_name:指定索引名,如果不指定Mysql默認col_name為索引值。 length:索引長度,僅字符串型才可指定 [ASC|DESC]:升序、降序
1、創建普通索引:
mysql> create database lxqdb; mysql> use lxqdb; mysql> create table book -> ( -> book_id int not null, -> book_name varchar(255) not null, -> authors varchar(255) not null, -> info varchar(255) null, -> comment varchar(255) null, -> year_publication year not null, -> INDEX(year_publication) -> );
查看:
mysql> show create table book \G KEY `year_publication` (`year_publication`) # 成功建立索引,mysql自動添加索引名:year_publication
查看索引是否被正確使用:
mysql> explain select * from book where year_publication=2018\G *************************** 1. row *************************** id: 1 select_type: SIMPLE # 表示簡單的select,不可以使用子查詢。其他取值:PRIMARY | UNION | SUBQUERY table: book # 行指定數據表名,它們被按照讀取的先後順序排列 type: ref # 行指定本數據表和其他數據表之間的關聯。其他取值:system | const | eq_ref | ref | range | index | ALL possible_keys: year_publication # 可以選用的索引 key: year_publication # 實際選用的索引 key_len: 1 # 索引按字節計算長度,值越小表示越快 ref: const # 關聯另一個數據表裏的列名 rows: 1 # 執行查詢時預計會從這個數據表裏讀出的數據行的個數 Extra: Using index condition # 關聯操作信息 1 row in set (0.00 sec)
2、創建唯一索引:
在比較大龐大的數據表中,為了減少索引列操作的時間。與普通索引唯一不同的是:索引列的值必須唯一,但允許有空值。如果是組合索引,則 列值的組合必須唯一。
創建tb1表,id字段使用UNIQUE創建唯一索引。
mysql> create table tb1 -> ( -> id int not null, -> name char(20) not null, -> UNIQUE INDEX uidx(id) -> );
查看:
mysql> show create table tb1\G UNIQUE KEY `uidx` (`id`) # id字段上創建了名為uidx的唯一索引。
3、創建單列索引:
單列索引是再數據表中某一字段上創建的索引,一個表中可以創建多個單列索引。
上面的兩個例子中創建的索引都是單列索引。
創建tb2表,在表中name字段上創建單列索引。
mysql> create table tb2 -> ( -> id int not null, -> name char(20) not null, -> INDEX Single_idx(name(10)) -> );
查看:
mysql> show create table tb2\G KEY `Single_idx` (`name`(10)) # name字段上創建名為Single_idx且長度10的單列索引。
4、創建組合索引:
在多個字段上創建索引。
創建tb3表,id,name,age為索引
mysql> create table tb3 -> ( -> id int not null, -> name char(20) not null, -> age int not null, -> info varchar(255), -> INDEX Multi_idx(id,name,age) -> );
查看:
mysql> show create table tb3\G KEY `Multi_idx` (`id`,`name`,`age`) # 建立了組合索引 註意:組合索引可起幾個索引的作用,但是使用時並不是隨便查詢哪個字段都可以使用索引,而是遵從“最左前綴” 最左前綴:利用索引中最左邊的列集來匹配,索引中按id\name\age的順序存放,索引可以搜索下面的字段組合:(id,name,age)、(id,name)、id。 如果列不構成索引最左前綴,mysql不能使用局部索引,如age或者name,age組合則不能使用索引。 查詢id和name字段的索引情況: mysql> explain select * from tb3 where id=1 and name='lxq'\G key: Multi_idx # 可以看到使用了MultiIdx的索引。 查詢name和age字段的索引情況: mysql> explain select * from tb3 where name='lxq' and age=23\G key: NULL # 表示並沒有使用索引查詢。
5、創建全文索引:
只有myisam引擎支持且只為char,varchar,text列。索引總是對整列進行,不支持局部索引。
創建表tb4,在info字段上建全文索引:
mysql> create table tb4 -> ( -> id int not null, -> name char(20) not null, -> age int not null, -> info varchar(255), -> FULLTEXT INDEX Fulltext_idx(info) -> )engine=myisam;
查看:
mysql> show create table tb4\G FULLTEXT KEY `Fulltext_idx` (`info`) # 名為Fulltext_idx的FULLTEXT。適合大型數據,不要在小數據內使用。
6、創建空間索引:
只有myisam引擎支持且只為not null列。
創建tb5表,GEOMETRY字段上創建空間索引:
mysql> create table tb5 -> ( -> gmt geometry not null, -> SPATIAL INDEX Spat_idx(gmt) -> )engine=myisam;
查看:
mysql> show create table t5\G;
SPATIAL KEY `Spat_idx` (`gmt`) # 名為Spat_idx的GEOMETRY
---------------------------------------------------------------------------------------
我是分割線1
---------------------------------------------------------------------------------------
已存在表中創建索引:
1、在book表中的bookname字段上建bookname_idx的普通索引:
mysql> alter table book add index bookname_idx(book_name(30));
查看:
mysql> show index from book\G *************************** 2. row *************************** Table: book Non_unique: 1 # 索引非唯一,1代表非唯一索引,0代表唯 Key_name: bookname_idx # 索引名 Seq_in_index: 1 # 索引中的位置,1為單列,組合索引為每個字段在索引定義中的順序 Column_name: book_name # 索引的列字段 Collation: A Cardinality: 0 Sub_part: 30 # 索引長度 Packed: NULL Null: # 字段是否為空 Index_type: BTREE # 索引類型 Comment: Index_comment: Table: book
2、在bookid字段上建立名為UniqidIdx的唯一索引:
mysql> alter table book add UNIQUE INDEX Uniqid_idx(book_id);
查看:
mysql> show index from book \G; *************************** 1. row *************************** Table: book Non_unique: 0 # 索引唯一,1代表非唯一索引,0代表唯一索 Key_name: Uniqid_idx Seq_in_index: 1
3、在comment上創建單列索引:
mysql> alter table book add INDEX coment_idx(comment(50));
查看:
mysql> show index from book \G Sub_part: 50 #只要檢索前50個字符
4、在book的authors和info上建組合索引:
mysql> alter table book add INDEX Au_Info_idx(authors(20),info(50));
查看:
mysql> show index from book \G; Key_name: Au_Info_idx Seq_in_index: 1 # 索引序列1 Column_name: authors ******************************* Key_name: Au_Info_idx Seq_in_index: 2 # 索引序列2 Column_name: info
5、在tb6表gmt字段建空間索引:
建表:
mysql> create table tb6 ( gmt geometry not null)engine=myisam;
增加空間索引:
mysql> alter table tb6 add SPATIAL INDEX spat_idx(gmt);
查看:
mysql>show index from tb6\G
---------------------------------------------------------------------------------------
我是分割線2
---------------------------------------------------------------------------------------
查看索引:
mysql> show create table book \G UNIQUE KEY `Uniqid_idx` (`book_id`), KEY `year_publication` (`year_publication`), KEY `bookname_idx` (`book_name`(30)), KEY `coment_idx` (`comment`(50)), KEY `Au_Info_idx` (`authors`(20),`info`(50)) 或 mysql>show index from book\G
刪除索引:
mysql> alter table book drop index Uniqid_idx; # 刪除索引名為Uniqid_idx的索引。
註意:
添加AUTO_INCREMENT約束字段的唯一索引不能被刪除。
或
mysql> drop index coment_idx on book; # 刪除book表內索引名為coment_idx的索引。
---------------------------------------------------------------------------------------
我是分割線3
---------------------------------------------------------------------------------------
總結:
1、索引對數據庫的如此重要,應該如何使用?
為數據庫選擇正確的索引是一項復雜的任務。
如果索引列較少,則需要的磁盤空間和維護開銷都較少。
如果在一個大表上創建了多種組合索引,索引文件也膨脹的很快。
另一面索引較多可覆蓋更多的查詢。
刪除創建索引不影響應用程序,也不影響數據庫架構,因此應嘗試多個不同的索引,從而建立最優的索引。
2、盡量使用短索引。
對字符串類型的字段進行索引,如果可能應該指定一個前綴長度。
例如:有一個char(255)的列,如果在前10個或30個字符內,多數值是唯一的,則不需要對整個列進行索引。
短索引不僅可以提高查詢速度而且可以節省磁盤空間、減少I/O操作。
3、是不是索引建立得越多越好?
合理的索引可以提高查詢速度,但是不是索引越多越好。在執行插入語句的時候,mysql要為新插入的記錄建立索引,所以過多的索引會導致插入操作變的非常慢。
原則上是只在查詢用的字段才建立索引。
4、為甚查詢語句中的索引沒有起作用?
在一些情況下,查詢語句中使用了帶有索引字段。但索引字段沒有起作用。
例如:在where 條件的like關鍵字匹配的字符串以“%”開頭,這種情況下不會起作用。
where條件中使用or關鍵字鏈接條件,如果有1個字段沒有使用索引,那麽其他的索引也不會起作用。
如果使用多列索引,但是沒有使用多列索引中的第一個字段,那麽多列索引也不會起作用。
Mysql之索引介紹