【索引】索引的作用?為什么能夠提高查詢速度?以及索引用法(索引的原理)


 

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

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

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

創建索引時,你需要確保該索引是應用在 SQL 查詢語句的條件(一般作為 WHERE 子句的條件)。

實際上,索引也是一張表,該表保存了主鍵與索引字段,並指向實體表的記錄。

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

建立索引會占用磁盤空間的索引文件。 

 

為什么能夠提高查詢速度?

索引就是通過事先排好序,從而在查找時可以應用二分查找等高效率的算法。
一般的順序查找,復雜度為O(n),而二分查找復雜度為O(log2n)。當n很大時,二者的效率相差及其懸殊。

舉個例子:
表中有一百萬條數據,需要在其中尋找一條特定id的數據。如果順序查找,平均需要查找50萬條數據。而用二分法,至多不超過20次就能找到。二者的效率差了2.5萬倍!

 

在一個或者一些字段需要頻繁用作查詢條件,並且表數據較多的時候,創建索引會明顯提高查詢速度,因為可由全表掃描改成索引掃描。

(無索引時全表掃描也就是要逐條掃描全部記錄,直到找完符合條件的,索引掃描可以直接定位)

 

不管數據表有無索引,首先在SGA的數據緩沖區中查找所需要的數據,如果數據緩沖區中沒有需要的數據時,服務器進程才去讀磁盤。
1、無索引,直接去讀表數據存放的磁盤塊,讀到數據緩沖區中再查找需要的數據。
2、有索引,先讀入索引表,通過索引表直接找到所需數據的物理地址,並把數據讀入數據緩沖區中。

 

索引有什么副作用嗎?

(1)索引是有大量數據的時候才建立的,沒有大量數據反而會浪費時間,因為索引是使用二叉樹建立.

(2)當一個系統查詢比較頻繁,而新建,修改等操作比較少時,可以創建索引,這樣查詢的速度會比以前快很多,同時也帶來弊端,就是新建或修改等操作時,比沒有索引或沒有建立覆蓋索引時的要慢。

(3)索引並不是越多越好,太多索引會占用很多的索引表空間,甚至比存儲一條記錄更多。
對於需要頻繁新增記錄的表,最好不要創建索引,沒有索引的表,執行insert、append都很快,有了索引以后,會多一個維護索引的操作,一些大表可能導致insert 速度非常慢。

 

 

 

例子:

 

 

 建立索引:(在username列建立索引)

ALTER table tableName ADD INDEX indexName(username)

 利用explain分析索引:    參考 :http://www.cnblogs.com/qlqwjy/p/7767479.html

 1.沒有查詢username(不用索引)

EXPLAIN SELECT * FROM USER

 

 

2.根據username進行比對:(使用索引) 

EXPLAIN SELECT * FROM USER WHERE username='qlq'

 

 

 

 

 

 索引用法:

普通索引
創建索引

這是最基本的索引,它沒有任何限制。它有以下幾種創建方式:

CREATE INDEX indexName ON mytable(username(length)); 

    如果是CHAR,VARCHAR類型,length可以小於字段實際長度;如果是BLOB和TEXT類型,必須指定 length。
修改表結構(添加索引)

    ALTER table tableName ADD INDEX indexName(columnName)

創建表的時候直接指定

CREATE TABLE mytable(  
 
ID INT NOT NULL,   
 
username VARCHAR(16) NOT NULL,  
 
INDEX [indexName] (username(length))  
 
);  

刪除索引的語法

DROP INDEX [indexName] ON mytable; 

ALTER TABLE `exam5`.`questions` DROP KEY `question_type_index`; 唯一索引 它與前面的普通索引類似,不同的就是:索引列的值必須唯一,但允許有空值。如果是組合索引,則列值的組合必須唯一。它有以下幾種創建方式: 創建索引 CREATE UNIQUE INDEX indexName ON mytable(username(length)) 修改表結構 ALTER table mytable ADD UNIQUE [indexName] (username(length)) 創建表的時候直接指定 CREATE TABLE mytable( ID INT NOT NULL, username VARCHAR(
16) NOT NULL, UNIQUE [indexName] (username(length)) ); 使用ALTER 命令添加和刪除索引 有四種方式來添加數據表的索引: ALTER TABLE tbl_name ADD PRIMARY KEY (column_list): 該語句添加一個主鍵,這意味着索引值必須是唯一的,且不能為NULL。 ALTER TABLE tbl_name ADD UNIQUE index_name (column_list): 這條語句創建索引的值必須是唯一的(除了NULL外,NULL可能會出現多次)。 ALTER TABLE tbl_name ADD INDEX index_name (column_list): 添加普通索引,索引值可出現多次。 ALTER TABLE tbl_name ADD FULLTEXT index_name (column_list):該語句指定了索引為 FULLTEXT ,用於全文索引。 以下實例為在表中添加索引。 mysql> ALTER TABLE testalter_tbl ADD INDEX (c); 你還可以在 ALTER 命令中使用 DROP 子句來刪除索引。嘗試以下實例刪除索引: mysql> ALTER TABLE testalter_tbl DROP INDEX c; 使用 ALTER 命令添加和刪除主鍵 主鍵只能作用於一個列上,添加主鍵索引時,你需要確保該主鍵默認不為空(NOT NULL)。實例如下: mysql> ALTER TABLE testalter_tbl MODIFY i INT NOT NULL; mysql> ALTER TABLE testalter_tbl ADD PRIMARY KEY (i); 你也可以使用 ALTER 命令刪除主鍵: mysql> ALTER TABLE testalter_tbl DROP PRIMARY KEY; 刪除主鍵時只需指定PRIMARY KEY,但在刪除索引時,你必須知道索引名。 顯示索引信息 你可以使用 SHOW INDEX 命令來列出表中的相關的索引信息。

 

mysql查看表索引

mysql> show index from tblname;

mysql> show keys from tblname;

· Table

表的名稱。

· Non_unique

如果索引不能包括重復詞,則為0。如果可以,則為1。

· Key_name

索引的名稱。

· Seq_in_index

索引中的列序列號,從1開始。

· Column_name

列名稱。

· Collation

列以什么方式存儲在索引中。在MySQL中,有值‘A’(升序)或NULL(無分類)。

· Cardinality

索引中唯一值的數目的估計值。通過運行ANALYZE TABLE或myisamchk -a可以更新。基數根據被存儲為整數的統計數據來計數,所以即使對於小型表,該值也沒有必要是精確的。基數越大,當進行聯合時,MySQL使用該索引的機 會就越大。

· Sub_part

如果列只是被部分地編入索引,則為被編入索引的字符的數目。如果整列被編入索引,則為NULL。

· Packed

指示關鍵字如何被壓縮。如果沒有被壓縮,則為NULL。

· Null

如果列含有NULL,則含有YES。如果沒有,則該列含有NO。

· Index_type

用過的索引方法(BTREE, FULLTEXT, HASH, RTREE)。

· Comment

 

 

  參考:http://www.jb51.net/article/73372.htm

 

自己的實踐:

1.單列建立索引

表名  questions

 結構:

 

未建立索引

  查看一個數據量非常大的試題表,根據試題的類型查:

SELECT * FROM questions WHERE TYPE='單選題'

 

結果:花費1062ms

/*[15:03:40][1062 ms]*/ SELECT * FROM questions WHERE TYPE='單選題'  LIMIT 0, 1000;    

 

 

 

用explain解釋語句之后:

EXPLAIN SELECT * FROM questions WHERE TYPE='單選題'

結果:可以簡單的看到一些參數,掃描了7134行,命中率大概為10%.

 

建立索引

 在type這一列建立索引

ALTER TABLE questions ADD INDEX index_ques_type(TYPE)

再次用explain分析執行語句

EXPLAIN SELECT * FROM questions WHERE TYPE='單選題'

 

結果: 掃描的行數明顯減少,且命中率明顯上升

 

2.建立組合索引

(1)未加索引

SELECT *
FROM questions
WHERE TYPE = '單選題'
    AND questionBankId = '40b7fedfbd1c4cc680d93782a033a518'

 

結果:

 

explain解釋執行

EXPLAIN
SELECT *
FROM questions
WHERE TYPE = '單選題'
    AND questionBankId = '40b7fedfbd1c4cc680d93782a033a518'

  

 

 (2)建立多列索引

ALTER TABLE `exam5`.`questions` ADD INDEX `index_duolie` (`questionBankId`, `type`)

 

(3) 查詢:(速度明顯提高)

SELECT *
FROM questions
WHERE 
    questionBankId = '40b7fedfbd1c4cc680d93782a033a518' AND TYPE = '單選題'

 

 explain解釋語句(使用了索引)

EXPLAIN
SELECT *
FROM questions
WHERE 
    questionBankId = '40b7fedfbd1c4cc680d93782a033a518' AND TYPE = '單選題'
    

  

 

 (4)查看索引

SHOW INDEX FROM questions

 

 

(5)使用單列索引中的一列

  1.只使用questionBankId 這一列看到查詢時使用了索引

EXPLAIN
SELECT *
FROM questions
WHERE 
    questionBankId = '40b7fedfbd1c4cc680d93782a033a518'

 

 

  2.只使用type這一列沒有使用索引

EXPLAIN
SELECT *
FROM questions
WHERE TYPE = '單選題'

  

  3 type和questionBankId交換位置使用索引

EXPLAIN
SELECT *
FROM questions
WHERE TYPE = '單選題'  AND questionBankId = '40b7fedfbd1c4cc680d93782a033a518'

  

  

總結:對於單列索引,使用where條件就可以進行查詢

  對於多列索引(A,B),如果where中只有A可以起到作用,只有B不會使用索引,A、B都有會使用索引,也就是在有A的條件下才會使用索引。

 

 

 

 

 

參考:

  http://www.runoob.com/mysql/mysql-index.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM