Mysql的索引是什麼?如何創建索引?創建索引的原則?怎麼優化?

索引的理解:

  索引是對數據庫表中的一列或多列的值進行排序的一種數據結構。
  索引的作用就類似於書本的目錄,新華字典的拼音,偏旁部首的首查字,可以快速的檢索到需要的內容,mysql在300萬條記錄性能就下降了,雖然mysql官方文檔說達500萬~800萬,所以當數據達到幾百萬的時候,那麼索引就很有必要了。
  當表中有大量記錄的時候,若要對錶進行查詢,第一種就是就需要把表中的記錄全部取出來,在和查詢條件一一對比,然後返回滿足條件的記錄、這樣做就會大大消耗數據庫系統的時間,並造成大量磁盤I/O操作;第二種就是在表中建立索引,然後在索引中找到符合查詢條件的索引值,最後通過保存在索引中ROWID(相當於頁碼)快速找到表中的記錄。

語句:

CREATE TABLE table_name[filed_name data type]
[unique|fulltext][index|key][index_name](filed_name[length])[asc|desc]

  1. unique|fulltext爲可選參數,分別表示唯一索引、全文索引
  2. index和key爲同義詞,兩者作用相同,用來指定創建索引
  3. filed_name爲需要創建索引的字段列,該列必須從數據表中該定義的多個列中選擇
  4. index_name指定索引的名稱,爲可選參數,如果不指定,默認filed_name爲索引值
  5. length爲可選參數,表示索引的長度,只有字符串類型的字段才能指定索引長度
  6. asc或desc指定升序或降序的索引值存儲

索引類型:

一、唯一索引(unique):列的值必須唯一,但允許有空值。如果是組合索引則列值必須唯一

1)、創建唯一索引

CREATE UNIQUE INDEX index_name ON table(column(length))

2)、修改表結構

ALTER TABLE table_name ADD UNIQUE INDEX index_name ON (column(length))

3)、創建表時直接指定

CREATE TABLE `table_name`(
`id` INT(11) NOT NULL AUTO_INCREMENT,
`code` INT(8) NOT NULL,
`title` VARCHAR(255) NOTNULL,
`content` TEXT,
`time` INT(10) NULL DEFAULT NULL,
UNIQUE index_name(code)
);

二、主鍵索引(primary key):是一特殊的唯一索引,一個表允許有一個主鍵,主鍵要求建表時指定.

CREATE TABLE `table_name`(
`id` INT(11) NOT NULL AUTO_INCREMENT,
`code` INT(8) NOT NULL,
`title` VARCHAR(255) NOTNULL,
`content` TEXT,
`time` INT(10) NULL DEFAULT NULL,
PRIMARY KEY(`id`)
);

三、普通索引(index):最基本的索引,沒有任何限制。如果是char,varchar類型,length可以小於字段長度、如果是BLOB和TEXT類型,必須指定長度。

1)、直接創建

CREATE INDEX index_name ON table(column(length))

2)、修改表結構的方式添加

ALTER TABLE table_name ADD INDEX index_name ON (column(length))

3)、創建表時直接指定

CREATE TABLE `table_name`(
`id` INT(11) NOT NULL AUTO_INCREMENT,
`title` VARCHAR(255) NOTNULL,
`content` TEXT,
`time` INT(10) NULL DEFAULT NULL,
PRIMARY KEY(`id`),
INDEX index_name(title(length))
);

4)、刪除索引

DROP INDEX index_name ON table

四、多列索引:指多個字段上創建的索引,只有在查詢條件中使用了創建索引時的第一個字段索引纔會使用。使用組合索引遵循最左前綴原則
五、全文索引(fulltext):主要是用來查找文本的關鍵字,而不是直接與索引中的值比較。fulltext索引跟其他索引大不相同,它更像一個搜索引擎,而不是簡單的where語句的參數匹配。fulltext要配合match against操作使用,而不是一般的where語句加like。它可以在create tablealter tablecreate index使用,不過目前只有char varchar text列上可以創建全文索引。

tip:全文索引只有MyISAM支持,不過在mysql5.6後Innodb也支持了

1)、創建表的時候添加全文索引


CREATE TABLE `table_name`(
`id` INT(11) NOT NULL AUTO_INCREMENT,
`title` VARCHAR(255) NOTNULL,
`content` TEXT,
`time` INT(10) NULL DEFAULT NULL,
FULLTEXT (content)
);

2)、修改表結構添加全文索引

ALTER TABLE table_name ADD FULLTEXT index_name(content)

3)、直接創建索引

CREATE FULLTEXT INDEX index_namet ON table_name(content)

缺點:

  1. 雖然索引大大的提升了查詢的速度,同時也降低了對錶的增刪改的速度,因爲更新表,不僅要保存數據,還要保存索引文件
  2. 建立索引會佔用磁盤空間。一般不太嚴重,如果你在一個大表上創建多種組合索引,索引文件會增長很快索引只是提高效率的一個因素,如果有大數據量的表,就要花時間研究建立最優秀的索引,或優化查詢語句

索引方式:

    對於BTREE和HASH索引,當使用=、<=>、IN、IS NULL或者IS NOT NULL操作符時,關鍵元素與常量值的比較關係對應一個範圍條件。Hash索引還有一些其它特徵:它們只用於使用=或<=>操作符的等式比較(但很快)。優化器不能使用hash索引來加速ORDER BY操作。(該類索引不能用來按順序搜索下一個條目)。MySQL不能確定在兩個值之間大約有多少行(這被範圍優化器用來確定使用哪個索引)。如果你將一個MyISAM表改爲hash-索引的MEMORY表,會影響一些查詢。只能使用整個關鍵字來搜索一行。(用B-樹索引,任何關鍵字的最左面的前綴可用來找到行)。

    對於BTREE索引,當使用>、<、>=、<=、BETWEEN、!=或者<>,或者LIKE ‘pattern’(其中 ‘pattern’不以通配符開始)操作符時,關鍵元素與常量值的比較關係對應一個範圍條件。“常量值”係指:查詢字符串中的常量、同一聯接中的const或system表中的列、無關聯子查詢的結果、完全從前面類型的子表達式組成的表達式。

下面是一些WHERE子句中有範圍條件的查詢的例子。
下列範圍查詢適用於 btree索引和hash索引:

SELECT * FROM t1 WHERE key_col = 1 OR key_col IN (15,18,20);

下列範圍查詢適用於btree索引

SELECT * FROM t1 WHERE key_col > 1 AND key_col < 10;
SELECT * FROM t1 WHERE key_col LIKE 'ab%' OR key_col BETWEEN 'bar' AND 'foo';

創建索引原則與使用索引注意事項:

  1. 選擇唯一索引

    唯一索引的值是唯一的,可以更快速的通過該索引確定某一條記錄

  2. 爲經常需要排序、分組和聯合操作的字段建立索引

    經常需要order by、 group by、distinct和union等操作的字段,排序會浪費很多時間,如果爲其建立索引,可以有效避免排序操作

  3. 經常作爲查詢條件的字段建立索引

    如果某個字段經常作爲查詢條件,name該字段的查詢速度就會影響整個表的速度。因此,爲這樣的字段建立索引,可以提高整個表的查詢速度

  4. 限制索引的數目

    索引的數目不是越多越好。每個索引都是要佔用磁盤空間的,索引越多,需要的磁盤空間就越大。修改表時,和更新會很麻煩。越多的索引,會使更新表變得很浪費時間

  5. 儘量使用數據量少的索引

    如果索引的值很長,那麼查詢的速度就會受到影響,例如對一個char(100)類型的字段進行全文檢索需要的時間肯定要比char(10)類型的字段需要的時間多得多,並且char(10)全文檢索而且可以節省磁盤空間和I/O操作。

  6. 儘量使用前綴來索引

    如果索引字段的值很長,最好使用值的前綴來索引。例如,TEXT和BLOG類型的字段,進行全文檢索會很浪費時間。如果只檢索字段的前面的若干個字符,這樣可以提高檢索速度。

  7. 刪除不再使用或者很少使用的索引

    表中的數據被大量更新,或者數據使用方式被改變後,原有的一些索引可能不在需要。數據庫管理員應當定期找出這些索引,將它們刪除。從而減少索引對更新操作的影響

  8. 最左前綴原則,非常重要的一個原則

    mysql會一直向右匹配知道遇到範圍查詢(>、<、between、like)就停止匹配,比如a=1 and b=2 and c>3 and d=4 如果建立(a,b,c,d)順序索引,d是用不到索引的,如果是建立(a,b,d,c)則可以都用到

  9. =和in可以亂序

    比如a = 1 and b = 2 and c = 3 建立(a,b,c)索引可以任意順序,mysql的查詢優化器會幫你優化成索引可以識別的形式

  10. 儘量選擇區分度高的列作爲索引。

    區分度的公式是count(distinct col)/count(*),表示字段不重複的比例,比例越大我們掃描的記錄數越少,唯一鍵的區分度是1,而一些狀態、性別字段可能在大數據面前區分度就 是0,那可能有人會問,這個比例有什麼經驗值嗎?使用場景不同,這個值也很難確定,一般需要join的字段我們都要求是0.1以上,即平均1條掃描10條 記錄

  11. 索引列不能參與計算,保持列“乾淨”。

    select * from users where YEAR(adddate)<'2007';
    將在每個行上進行運算,這將導致索引失效而進行全表掃描,因此我們可以改成:
    select * from users where adddate<‘2007-01-01';

  12. 儘量的擴展索引,不要新建索引。

    比如表中已經有a的索引,現在要加(a,b)的索引,那麼只需要修改原來的索引即可

  13. 不使用NOT IN和<>操作

  14. like語句操作

    一般情況下不鼓勵使用like操作,如果非使用不可,如何使用也是一個問題。like “%aaa%” 不會使用索引而like “aaa%”可以使用索引。

  15. 索引列排序

    MySQL查詢只使用一個索引,因此如果where子句中已經使用了索引的話,那麼order by中的列是不會使用索引的。因此數據庫默認排序可以符合要求的情況下不要使用排序操作;儘量不要包含多個列的排序,如果需要最好給這些列創建複合索引。

  16. 索引不會包含有NULL值的列

    只要列中包含有NULL值都將不會被包含在索引中,複合索引中只要有一列含有NULL值,那麼這一列對於此複合索引就是無效的。所以我們在數據庫設計時不要讓字段的默認值爲NULL。


注意:選擇索引的最終目的是爲了使查詢的速度變快。上面給出的原則是最基本的準則,但不能拘泥於上面的準則。讀者要在以後的學習和工作中進行不斷的實踐。根據應用的實際情況進行分析和判斷,選擇最合適的索引方式。

索引優化:

一、導致SQL執行慢的原因

  1. 硬件問題。如網絡速度慢,內存不足,I/O吞吐量少,磁盤空間滿了等。
  2. 沒有索引或索引失效。
  3. 數據過多(分庫分表)。
  4. 服務器調優及各個參數設置(調整my.cnf)

二、分析原因時,一定要找切入點

  1. 先觀察,開啓慢查詢日誌,設置相應的閾值(比如超過2秒就是慢SQL),在生產環境上跑一天以後,看看那些SQL比較慢
  2. Explain和慢SQL分析。比如寫的爛的SQL語句,索引沒有或失效,關聯查詢太多(有時候是設計缺陷或者不得已的需求)等等
  3. Show Profile是比Explain更進一步的執行細節,可以查詢到每一個SQL都幹了些什麼事,這些事分別花了多少時間
  4. 找DBA或運維對MYsql進行服務器參數調優

Explain 與 Show Profile詳情下兩章介紹

參考:https://blog.csdn.net/GV7lZB0y87u7C/article/details/79969293
   https://blog.csdn.net/u013412790/article/details/51612304

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章