溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Mysql之索引介紹

發(fā)布時(shí)間:2020-07-23 03:21:03 來源:網(wǎng)絡(luò) 閱讀:2113 作者:一葉扁舟丶 欄目:MySQL數(shù)據(jù)庫

定義:

索引用于快速找出某個(gè)列中有一特定值的行。

不使用索引,MySql必須從第一條記錄開始讀完整個(gè)表,直到找出相關(guān)的行。表越大,查詢數(shù)據(jù)所花費(fèi)的時(shí)間越多。

如果表中查詢的列有一個(gè)索引,Mysql能快速到達(dá)一個(gè)位置去搜索數(shù)據(jù)文件,而不必查看所有數(shù)據(jù)。


簡介:

索引是對數(shù)據(jù)庫表中一列或多列的值進(jìn)行排序的一種結(jié)構(gòu),使用索引可以提高數(shù)據(jù)庫中特定數(shù)據(jù)的查詢速度。

索引是一個(gè)單獨(dú)的、存儲(chǔ)在磁盤上的數(shù)據(jù)庫結(jié)構(gòu),他們包含著對數(shù)據(jù)表里所有記錄的引用指針。

使用索引用于快速找出某個(gè)或者多個(gè)列中有一特定值的行,所有Mysql列類型都可以被索引,對相關(guān)列使用索引是提高查詢操作速度的最佳途徑。

例如:數(shù)據(jù)庫中有2萬條記錄,現(xiàn)在要執(zhí)行這樣一個(gè)查詢:

select * from table where num=10000

如果沒有索引,必須遍歷整個(gè)表,直到num等于10000的這一行被找到為止。

如果在num列上創(chuàng)建索引,MySql不需要任何掃描,直接在索引里面找到10000,就可以得知這一行的位置。

索引是存儲(chǔ)引擎實(shí)現(xiàn)的,因此,每種存儲(chǔ)引擎的索引都不一定完全相同,并且每種存儲(chǔ)引擎也不一定支持所有索引類型。

根據(jù)存儲(chǔ)引擎定義每個(gè)表的最大索引數(shù)和最大索引長度。所有存儲(chǔ)引擎支持每個(gè)表至少16個(gè)索引,總索引長度至少為256字節(jié)。大多數(shù)存儲(chǔ)引擎有更高的限制。

MySql中索引的存儲(chǔ)類型有兩種:BTREE和HASH,具體和表的存儲(chǔ)引擎相關(guān);MyISAM和InnoDB存儲(chǔ)引擎都支持BTREE索引;MEMORY/HEAP存儲(chǔ)引擎可以支持BTREE和HASH索引。


索引優(yōu)點(diǎn):

1、通過創(chuàng)建唯一索引,可以保證數(shù)據(jù)庫表中每一行數(shù)據(jù)的唯一性。

2、可以大大加快數(shù)據(jù)的查詢速度,這也是創(chuàng)建索引的最主要的原因。

3、在實(shí)現(xiàn)數(shù)據(jù)的參考完整性方面,可以加速表和表之間的鏈接。

4、在使用分組和排序子句進(jìn)行數(shù)據(jù)查詢時(shí),也可以顯著減少查詢中分組和排序的時(shí)間。


索引的缺點(diǎn):

1、創(chuàng)建索引和維護(hù)索引要耗費(fèi)時(shí)間,并且隨著數(shù)據(jù)量的增加所耗費(fèi)的時(shí)間也會(huì)增加。

2、索引需要占據(jù)磁盤空間,除了數(shù)據(jù)表占數(shù)據(jù)空間之外,每一個(gè)索引還要占一定的物理空間,如果有大量的索引,索引文件可能比數(shù)據(jù)文件更快達(dá)到最大文件尺寸。

3、當(dāng)對表中的數(shù)據(jù)進(jìn)行增加、刪除和修改的時(shí)候,索引也要?jiǎng)討B(tài)維護(hù),這樣就降低了數(shù)據(jù)的維護(hù)速度。


MySql索引的分類:

1、普通索引和唯一索引

    普通索引:Mysql中最基礎(chǔ)的索引類型,允許在定義索引的列中插入重復(fù)值和空值。

    唯一索引:索引列的值必須唯一,但允許有空值。

如果是組合索引,則列值和組合必須唯一。主鍵索引是一種特殊唯一索引,不行允許有空值。

2、單列索引和組合索引

    單列索引:一個(gè)索引只包含一個(gè)列,一個(gè)表也可以有多個(gè)單列索引。

    組合索引:在表的多個(gè)字段組合上創(chuàng)建的索引,只有在查詢條件中使用了這些字段的左邊字段時(shí),索引才會(huì)被使用。使用組合索引時(shí)遵循最左前綴集合。

3、全文索引

    全文索引類型為FULLTEXT,在定義索引的列上支持值得全文查找,允許在這些索引列中插入重復(fù)值和空值。全文索引可以在CHAR,VARCHAR或者TEXT類型上創(chuàng)建。

只有MyISAM存儲(chǔ)引擎支持全文索引。

4、空間索引

    空間索引是對空間數(shù)據(jù)類型的字段建立索引,Mysql中的空間數(shù)據(jù)有4中:GEOMETRY、POINT、LINESTRING和POLYGON。Mysl使用SPATIAL關(guān)鍵字進(jìn)行擴(kuò)展,使得能夠創(chuàng)建正規(guī)索引類似的語法創(chuàng)建空間索引。

創(chuàng)建空間索引的列,必須將其聲明為NOT NULL,空間索引只能在存儲(chǔ)引擎為MyISAM中創(chuàng)建。


索引表的設(shè)計(jì)原則:

1、索引表不是越多越好,一個(gè)表中如果有大量索引,不僅占用硬盤空間,還影響增刪改查等語句的性能,因?yàn)楫?dāng)表中的數(shù)據(jù)更改的同時(shí),索引也會(huì)進(jìn)行調(diào)整和更新。

2、避免經(jīng)常更新的表進(jìn)行過多的索引,并且索引表中的列盡可能少。而經(jīng)常查詢的字段應(yīng)該創(chuàng)建索引,但要避免添加不必要的字段。

3、數(shù)據(jù)量小的表最好不要使用索引。遍歷的時(shí)間短與索引的時(shí)候,并不會(huì)產(chǎn)生優(yōu)化效果。

4、在條件表達(dá)式中經(jīng)常用到的不同值較多的列上建立索引,在不同值少的列上不要建立索引。比如性別。

5、當(dāng)唯一性是某種數(shù)據(jù)本身的特征時(shí),指定唯一索引。使用唯一索引需要能確保定義的列的數(shù)據(jù)的完整性,以提高數(shù)據(jù)的查詢速度。

6、在頻繁進(jìn)行排序或者分組(即進(jìn)行g(shù)roup by 或order by操作)的列上建立索引,如果待排序的列有多個(gè),可以在這些列上建立組合索引。

創(chuàng)建語法:

CREATE TABLE 指定索引列
ALTER TABLE 在存在的表上創(chuàng)建索引
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]:作用相同,創(chuàng)建索引
col_name:需要?jiǎng)?chuàng)建索引的字段列,必須在表中定義的列
index_name:指定索引名,如果不指定Mysql默認(rèn)col_name為索引值。
length:索引長度,僅字符串型才可指定
[ASC|DESC]:升序、降序

1、創(chuàng)建普通索引:

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自動(dòng)添加索引名: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         # 行指定數(shù)據(jù)表名,它們被按照讀取的先后順序排列
             type: ref          # 行指定本數(shù)據(jù)表和其他數(shù)據(jù)表之間的關(guān)聯(lián)。其他取值:system | const | eq_ref | ref | range | index | ALL
         possible_keys: year_publication         # 可以選用的索引
              key: year_publication         # 實(shí)際選用的索引
            key_len: 1                   # 索引按字節(jié)計(jì)算長度,值越小表示越快
              ref: const         # 關(guān)聯(lián)另一個(gè)數(shù)據(jù)表里的列名
             rows: 1           # 執(zhí)行查詢時(shí)預(yù)計(jì)會(huì)從這個(gè)數(shù)據(jù)表里讀出的數(shù)據(jù)行的個(gè)數(shù)
             Extra: Using index condition      # 關(guān)聯(lián)操作信息
    1 row in set (0.00 sec)


2、創(chuàng)建唯一索引:

在比較大龐大的數(shù)據(jù)表中,為了減少索引列操作的時(shí)間。與普通索引唯一不同的是:索引列的值必須唯一,但允許有空值。如果是組合索引,則 列值的組合必須唯一。

創(chuàng)建tb1表,id字段使用UNIQUE創(chuàng)建唯一索引。

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字段上創(chuàng)建了名為uidx的唯一索引。


3、創(chuàng)建單列索引:

單列索引是再數(shù)據(jù)表中某一字段上創(chuàng)建的索引,一個(gè)表中可以創(chuàng)建多個(gè)單列索引。

上面的兩個(gè)例子中創(chuàng)建的索引都是單列索引。

創(chuàng)建tb2表,在表中name字段上創(chuàng)建單列索引。

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字段上創(chuàng)建名為Single_idx且長度10的單列索引。

4、創(chuàng)建組合索引:

在多個(gè)字段上創(chuàng)建索引。

創(chuàng)建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`)            # 建立了組合索引

注意:組合索引可起幾個(gè)索引的作用,但是使用時(shí)并不是隨便查詢哪個(gè)字段都可以使用索引,而是遵從“最左前綴”
最左前綴:利用索引中最左邊的列集來匹配,索引中按id\name\age的順序存放,索引可以搜索下面的字段組合:(id,name,age)、(id,name)、id。
如果列不構(gòu)成索引最左前綴,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、創(chuàng)建全文索引:

只有myisam引擎支持且只為char,varchar,text列。索引總是對整列進(jìn)行,不支持局部索引。

創(chuàng)建表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。適合大型數(shù)據(jù),不要在小數(shù)據(jù)內(nèi)使用。


6、創(chuàng)建空間索引:

只有myisam引擎支持且只為not null列。

創(chuàng)建tb5表,GEOMETRY字段上創(chuàng)建空間索引:

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

---------------------------------------------------------------------------------------

已存在表中創(chuàng)建索引:

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為單列,組合索引為每個(gè)字段在索引定義中的順序
       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上創(chuàng)建單列索引:

mysql> alter table book add INDEX coment_idx(comment(50));

查看:

mysql> show index from book \G

Sub_part: 50        #只要檢索前50個(gè)字符

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表內(nèi)索引名為coment_idx的索引。

---------------------------------------------------------------------------------------

                                         我是分割線3

---------------------------------------------------------------------------------------

總結(jié):

1、索引對數(shù)據(jù)庫的如此重要,應(yīng)該如何使用?

為數(shù)據(jù)庫選擇正確的索引是一項(xiàng)復(fù)雜的任務(wù)。

如果索引列較少,則需要的磁盤空間和維護(hù)開銷都較少。

如果在一個(gè)大表上創(chuàng)建了多種組合索引,索引文件也膨脹的很快。

另一面索引較多可覆蓋更多的查詢。

刪除創(chuàng)建索引不影響應(yīng)用程序,也不影響數(shù)據(jù)庫架構(gòu),因此應(yīng)嘗試多個(gè)不同的索引,從而建立最優(yōu)的索引。


2、盡量使用短索引。

對字符串類型的字段進(jìn)行索引,如果可能應(yīng)該指定一個(gè)前綴長度。

例如:有一個(gè)char(255)的列,如果在前10個(gè)或30個(gè)字符內(nèi),多數(shù)值是唯一的,則不需要對整個(gè)列進(jìn)行索引。

短索引不僅可以提高查詢速度而且可以節(jié)省磁盤空間、減少I/O操作。


3、是不是索引建立得越多越好?

合理的索引可以提高查詢速度,但是不是索引越多越好。在執(zhí)行插入語句的時(shí)候,mysql要為新插入的記錄建立索引,所以過多的索引會(huì)導(dǎo)致插入操作變的非常慢。

原則上是只在查詢用的字段才建立索引。


4、為甚查詢語句中的索引沒有起作用?

在一些情況下,查詢語句中使用了帶有索引字段。但索引字段沒有起作用。

例如:在where 條件的like關(guān)鍵字匹配的字符串以“%”開頭,這種情況下不會(huì)起作用。

where條件中使用or關(guān)鍵字鏈接條件,如果有1個(gè)字段沒有使用索引,那么其他的索引也不會(huì)起作用。

如果使用多列索引,但是沒有使用多列索引中的第一個(gè)字段,那么多列索引也不會(huì)起作用。


向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI