1. 程式人生 > >mysql 索引建立與使用

mysql 索引建立與使用

文章目錄

1、mysql索引作用:

在索引列上,除了有序查詢之外,資料庫利用各種各樣的快速定位技術,能夠大大提高查詢效率。特別是當資料量非常大,查詢涉及多個表時,使用索引往往能使查詢速度加快成千上萬倍。

2、mysql索引建立規則:

  • 1、表的主鍵、外來鍵必須有索引;
  • 2、資料量超過300的表應該有索引;
  • 3、經常與其他表進行連線的表,在連線欄位上應該建立索引
  • 4、經常出現在 Where子句中的欄位,特別是大表的欄位,應該建立索引;
  • 5、索引的欄位必須是經常作為查詢條件的欄位;
  • 6、索引應該建在小欄位上,對於大的文字欄位甚至超長欄位,不要建索引;
  • 7、頻繁進行資料操作的表,不要建立太多的索引;
  • 8、刪除無用的索引,避免對執行計劃造成負面影響;
  • 9、不要過度索引。不要以為 索引 “ 越多越好 ” ,什麼東西都用索引是錯的。每個額外的 索引都要佔用額外的磁碟空間,並降低寫操作的效能。如果想給已索引的表增加索引,應該考慮所要增加的索引是否是現有多列索引的最左索引。如果是,則就不要費力去增加這個索引了,因為已經有了。
  • 10、考慮在列上進行的比較型別。索引可用於 “ < ” 、 “ < = ” 、 “ = ” 、 “ > = ” 、 “ >” 和 BETWEEN 運算。在模式具有一個直接量字首時,索引也用於 LIKE 運算。
  • 11、對於值唯一不重複的列要新增唯一索引,可以更快速的通過該索引來確定某條記錄。唯一索引是最有效的。

複合索引的建立需要進行仔細分析;儘量考慮用 單欄位索 引代替:

  • A、正確選擇複合索引中的主列欄位,一般是選擇性較好的欄位;
  • B、複合索引的幾個欄位是否經常同時以AND方式出現在Where子句中?單欄位查詢是否極少甚至沒有?如果是,則可以建立複合索引;否則考慮單欄位索引;
  • C、如果複合索引中包含的欄位經常單獨出現在Where子句中,則分解為多個單欄位索引;
  • D、如果複合索引所包含的欄位超過3個,那麼仔細考慮其必要性,考慮減少複合的欄位;
  • E、如果既有單欄位索引,又有這幾個欄位上的複合索引,一般可以刪除複合索引;
  • F、如果索引多個欄位,第一個欄位要是經常作為查詢條件的。如果只有第二個欄位作為查詢條件,這個索引不會起到作用;

3、索引的問題

索引對於插入、刪除、更新操作也會增加處理上的開銷。

另外,過多的複合索引,在有單欄位索引的情況下,一般都是沒有存在價值的;相反,還會降低資料增加刪除時的效能,特別是對頻繁更新的表來說,負面影響更大。

4、建立索引:

4.1、執行CREATE TABLE語句時可以建立索引:

例項:

CREATE TABLE `log_day_url_body` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `body` varchar(255) NOT NULL DEFAULT '',
  `p_id` int(11) NOT NULL DEFAULT '0',
  `plt_id` int(3) NOT NULL DEFAULT '1',
  primary key (`id`),
  KEY `body` (`body`),
  KEY `categories` (`body`,`plt_id`,`p_id`),
   unique  KEY `url` (`id`,`plt_id`,`p_id`),
   unique  KEY `url_3` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='註釋語句'

4.2、單獨用 CREATE INDEX 來為表增加索引:

CREATE INDEX 可對錶增加普通索引 或 unique 索引。

CREATE INDEX index_name ON table_name (column_list)
CREATE  unique  INDEX index_name ON table_name (column_list)

table_name、index_name 和 column_list 具有 與 ALTER TABLE 語句中相同的含義,索引名不可選。另外,不能用 CREATE INDEX 語句建立 primary key 索引。

4.3、單獨用ALTER TABLE來為表增加索引:

ALTER TABLE用來建立普通索引、 unique 索引或primary key索引。

ALTER TABLE table_name ADD INDEX index_name (column_list)
ALTER TABLE table_name ADD  unique  (column_list)
ALTER TABLE table_name ADD primary key (column_list)
'新增FULLTEXT(全文索引)'
ALTER TABLE `table_name` ADD FULLTEXT ( `column`)
ALTER TABLE `table_name` ADD INDEX index_name ( `column1`, `column2`, `column3` )

column_list指出對哪些列進行索引,多列時各列之間用逗號分隔。索引名index_name可選,預設時,MySQL將根據第一個索引列賦一個名稱。另外,ALTER TABLE允許在單個語句中更改多個表,因此可以在同時建立多個索引。

5、索引型別:

在建立索引時,可以規定索引能否包含重複值。如果不包含,則索引應該建立為 primary key 或 unique 索引。
對於單列惟一性索引,這保證單列不包含重複的值。對於多列惟一性索引,保證多個值的組合不重複。
primary key索引和 unique 索引非常類似。事實上,primary key索引僅是一個具有名稱PRIMARY的 unique 索引。
這表示一個表只能包含一個primary key,因為一個表中不可能具有兩個同名的索引。

6、刪除索引:

可利用 ALTER TABLE 或 DROP INDEX 語句來刪除索引。drop index 可以在 alter table 內部作為一條語句處理,語法如下。

DROP INDEX index_name ON talbe_name
ALTER TABLE table_name DROP INDEX index_name
ALTER TABLE table_name DROP primary key

其中,前兩條語句是等價的,刪除掉table_name中的索引index_name。

第3條語句只在刪除 primary key 索引時使用,因為一個表只可能有一個 primary key 索引,因此不需要指定索引名。

如果沒有建立 primary key 索引,但表具有一個或多個 unique 索引,則MySQL將刪除第一個 unique 索引。

如果從表中刪除了某列,則索引會受到影響。對於多列組合的索引,如果刪除其中的某列,則該列也會從索引中刪除。

如果刪除組成索引的所有列,則整個索引將被刪除。

7、檢視索引:

show index from tblname;
'或'
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
一些關於過引的常用語句

8、索引使用注意事項:

8.1、不要對 索引欄位 進行運算

不要對索引欄位進行運算,而要想辦法做變換,比如

SELECT ID FROM T WHERE NUM/2=100
'應改為:'
SELECT ID FROM T WHERE NUM = 100*2

SELECT ID FROM T WHERE NUM/2 = NUM1
'如果NUM有索引應改為:'
SELECT ID FROM T WHERE NUM = NUM1*2
如果NUM1有索引則不應該改。
SELECT,,金額 FROM 結餘表 WHERE 100*+=2010*100+10

'改為:'

SELECT,,金額 FROM 結餘表 WHERE=2010 AND=10

8.2、不要對 索引欄位 進行 格式轉換

日期欄位的例子

WHERE CONVERT(VARCHAR(10), 日期欄位, 120) = '2010-07-15'

'應該改為'

WHERE日期欄位〉='2010-07-15' AND 日期欄位

IS NULL 轉換的例子:

WHERE ISNULL(欄位,'12')<>'12' 應改為: WHERE欄位<>'12'
WHERE ISNULL(欄位,'')='' 不應修改
WHERE ISNULL(欄位,'F') ='T' 應改為: WHERE欄位='T'
WHERE ISNULL(欄位,'F')<>'T' 不應修改

8.3、不要對 索引欄位 使用 函式

WHERE LEFT(NAME, 3)=’ABC’ 或者 WHERE SUBSTRING(NAME,1, 3)=’ABC’
應改為: WHERE NAME LIKE ‘ABC%

日期查詢的例子:

WHERE DATEDIFF(DAY, 日期,2010-06-30)=0
應改為:WHERE 日期>=2010-06-30AND 日期

WHERE DATEDIFF(DAY, 日期,2010-06-30)>0
應改為:WHERE 日期

WHERE DATEDIFF(DAY, 日期,2010-06-30)>=0
應改為:WHERE 日期

WHERE DATEDIFF(DAY, 日期,2010-06-30)  
應改為:WHERE 日期>=2010-07-01WHERE DATEDIFF(DAY, 日期,2010-06-30)
應改為:WHERE 日期>=2010-06-30

8.4、不要對 索引欄位 進行 多欄位 連線

比如:

WHERE FAME+.+LNAME=’HAIWEI.YANG’
應改為:
WHERE FNAME=’HAIWEI’ AND LNAME=’YANG’