MySQL單列索引和組合索引的區別介紹

 

轉載 ,如果涉及版權,請聯繫刪除 : http://blog.csdn.net/wxwzy738/article/details/17590305

MySQL單列索引是我們使用MySQL數據庫中經常會見到的,MySQL單列索引和組合索引的區別可能有很多人還不是十分的瞭解,下面就爲您分析兩者的主要區別,供您參考學習。

  爲了形象地對比兩者,再建一個表:

 

CREATE TABLE myIndex ( i_testID INT NOT NULL AUTO_INCREMENT, 
vc_Name VARCHAR(50) NOT NULL, 
vc_City VARCHAR(50) NOT NULL, i_Age INT NOT NULL, i_SchoolID INT NOT NULL, 
PRIMARY KEY (i_testID) );

 

  在這 10000 條記錄裏面 7 上 8 下地分佈了 5 條 vc_Name="erquan" 的記錄,只不過 city,age,school 的組合各不相同。

  來看這條T-SQL:

 

SELECT i_testID FROM myIndex WHERE vc_Name='erquan' AND vc_City='鄭州' AND i_Age=25;

 

  首先考慮建MySQL單列索引:

  在vc_Name列上建立了索引。執行 T-SQL 時,MYSQL 很快將目標鎖定在了vc_Name=erquan 的 5 條記錄上,取出來放到一中間結果集。在這個結果集裏,先排除掉 vc_City 不等於"鄭州"的記錄,再排除 i_Age 不等於 25 的記錄,最後篩選出唯一的符合條件的記錄。

  雖然在 vc_Name 上建立了索引,查詢時MYSQL不用掃描整張表,效率有所提高,但離我們的要求還有一定的距離。同樣的,在 vc_City 和 i_Age 分別建立的MySQL單列索引的效率相似。

  爲了進一步榨取 MySQL 的效率,就要考慮建立組合索引。就是將 vc_Name,vc_City,i_Age 建到一個索引裏:

 

ALTER TABLE myIndex ADD INDEX name_city_age (vc_Name(10),vc_City,i_Age);

 

  建表時,vc_Name 長度爲 50,這裏爲什麼用 10 呢?因爲一般情況下名字的長度不會超過 10,這樣會加速索引查詢速度,還會減少索引文件的大小,提高 INSERT 的更新速度。

  執行 T-SQL 時,MySQL 無須掃描任何記錄就到找到唯一的記錄。

  肯定有人要問了,如果分別在 vc_Name,vc_City,i_Age 上建立單列索引,讓該表有 3 個單列索引,查詢時和上述的組合索引效率一樣嗎?大不一樣,遠遠低於我們的組合索引。雖然此時有了三個索引,但 MySQL 只能用到其中的那個它認爲似乎是最有效率的單列索引。

  建立這樣的組合索引,其實是相當於分別建立了

 

vc_Name,vc_City,i_Age vc_Name,vc_City vc_Name

 

  這樣的三個組合索引!爲什麼沒有 vc_City,i_Age 等這樣的組合索引呢?這是因爲 mysql 組合索引“最左前綴”的結果。簡單的理解就是隻從最左面的開始組合。並不是只要包含這三列的查詢都會用到該組合索引,下面的幾個 T-SQL 會用到:

 

SELECT * FROM myIndex WHREE vc_Name="erquan" AND vc_City="鄭州"

SELECT * FROM myIndex WHREE vc_Name="erquan"

 

  而下面幾個則不會用到:

SELECT * FROM myIndex WHREE i_Age=20 AND vc_City="鄭州" 
SELECT * FROM myIndex WHREE vc_City="鄭州"

 

轉:http://blog.sina.com.cn/s/blog_4e45b8430102v6qw.html

到這裏我們已經學會了建立索引,那麼我們需要在什麼情況下建立索引呢?一般來說,在WHERE和JOIN中出現的列需要建立索引,但也不完全如此,因爲 MySQL只對<,<=,=,>,>=,BETWEEN,IN,以及某些時候的LIKE纔會使用索引。例如:

SELECT t.Name 

  •  
  • FROM mytable t LEFT JOIN mytable m   
  •  
  • ON t.Name=m.username WHERE m.age=20 AND m.city='鄭州' 

剛纔提到只有某些時候的LIKE才需建立索引。因爲在以通配符%和_開頭作查詢時,MySQL不會使用索引。例如下句會使用索引:

SELECT * FROM mytable WHERE username like'admin%' 

 

  • SELECT * FROM mytable WHEREt Name like'�min' 

(6)索引的不足之處

◆雖然索引大大提高了查詢速度,同時卻會降低更新表的速度,如對錶進行INSERT、UPDATE和DELETE。因爲更新表時,MySQL不僅要保存數據,還要保存一下索引文件。

索引只是提高效率的一個因素,如果你的MySQL有大數據量的表,就需要花時間研究建立最優秀的索引,或優化查詢語句。

使用索引時,有以下一些技巧和注意事項:

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

對串列進行索引,如果可能應該指定一個前綴長度。例如,如果有一個CHAR(255)的列,如果在前10個或20個字符內,多數值是惟一的,那麼就不要對整個列進行索引。短索引不僅可以提高查詢速度而且可以節省磁盤空間和I/O操作。

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

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

 

  • select * from users where YEAR(adddate)<2007; 

 

  • select * from users where adddate<‘2007-01-01’;  

◆不使用NOT IN和<>操作

 

一個Web報表項目的性能分析和優化實踐(四):MySQL建立索引,唯一索引和組合索引

先大致介紹下項目的數據庫信息。

數據庫A:主要存放的通用的表,如User、Project、Report等。

數據庫B、C、D:一個項目對應一個數據庫,而且這幾個項目的表是完全一樣的。

數據庫表的特點

A中的表:數據量幾乎都比較小,比如User表中用戶數,頂多也就幾百上千。

B中的表:X/Y/Z 3張表幾乎是確定的,Data表 中的數據量比較大,幾千萬到上億。

週期性的會加入一大批數據,比如,每月末增加幾百萬條數據。

即一般情況下,B中的表只有查詢操作,而且特別是Data查詢頻繁且數據量很大。

建立索引

1.爲所有的表建立了唯一索引,索引字段是主鍵id。

2.考慮到數據庫A中表的數據量很小,暫時沒有建立組合索引。

如有可能,對頻繁查詢的表和字段,後期嘗試加入組合索引。

3.對Data表建立組合索引。

頻繁查詢的一條SQL語句

select  from Data where projectId=? and (inputVersion in (201)) and (sideId in (10001)) and (breakId in (?)) and (periodId in (?))  order by id desc;

建立組合索引的語句
ALTER TABLE Data ADD INDEX data_query_index (projectId,inputVersion,sideId,breakId,periodId);

建立索引之前,需要花費2.796秒。

建立索引之後,只需要0.136秒。

可以說是,大幅度提升了查詢效率。

索引的弊端

隨之而來的問題:如果已經建立了索引,那麼批量增加數據的時候,會特別慢。

一種較快的方法是:批量插入數據之前,先刪除索引,提高批量插入數據的效率。
然後,再重新建立索引,提高查詢效率。

1000萬條記錄,重建5個字段的組合索引需要2到3秒。(我的兩個字段的組合索引過了好幾分鐘還沒結束!!!!!!!!!!!!!懷疑他的數據太簡單了,自己構造的,)

重建索引的問題是,這個過程中,查詢會比較慢。

應對之策:導入數據,重建索引 應該選擇 晚上/凌晨等用戶較少使用系統的時間段。

一個建議
 用 explain sql;
 可以分析sql語句的執行情況,進而對sql語句進行優化。

天下武功,唯勤不破

性能優化,以前只是看過一些書,沒啥實踐經驗。

最近項目需要由我來進行優化,只好硬着頭皮一點點去實踐。

網上搜資料、請教同事、請教大牛。

週末再多看看書,認真複習和學習Linux、MySQL、Tomcat、Redis等一大堆,先側重系統優化。

 

 

使用索引提高查詢速度
1.前言

在web開發中,頁面模板,業務邏輯(包括緩存、連接池)和數據庫這三個部分,數據庫在其中負責執行SQL查詢並返回查 詢結果,是影響網站速度最重要的性能瓶頸。本文主要針對MySql數據庫,雙十一的電商大戰,引發了淘寶技術熱議,而淘寶現在去IOE(I代表IBM的縮 寫,即去IBM的存儲設備和小型機;O是代表Oracle的縮寫,也即去Oracle數據庫,採用MySQL和Hadoop替 代的解決方案,;E是代表EMC2,即去EMC2的設備性,用PC Server替代EMC2),大量採用MySql集羣!讓MySql再次成爲耀眼的明星!而優化數據的重要一步就是索引的建立,對於mysql中出現的慢 查詢,我們可以通過使用索引來提升查詢速度。索引用於快速找出在某個列中有一特定值的行。不使用索引,MySQL將進行全表掃描,從第1條記錄開始然後讀 完整個表直到找出相關的行。

2.mysql索引類型及創建
常用的索引類型有

(1)主鍵索引
它是一種特殊的唯一索引,不允許有空值。一般是在建表的時候同時創建主鍵索引:

代碼如下:


CREATE TABLE user(
id int unsigned not null auto_increment,
name varchar(50) not null,
email varchar(40) not null,
primary key (id)
);


(2)普通索引
這是最基本的索引,它沒有任何限制。創建方式:

代碼如下:


create index idx_name on user(
name(20)
);


mysql支持前綴索引,一般姓名不會超過20個字符,所以我們這裏建立索引的時候限定了長度20,這樣可以節省索引文件大小

(3)唯一索引
它與前面的普通索引類似,不同的就是:索引列的值必須唯一,但允許有空值。如果是組合索引,則列值的組合必須唯一。創建方式:

複製代碼 代碼如下:


CREATE UNIQUE INDEX idx_email ON user(
email
);


(4)全文索引
MySQL支持全文索引和搜索功能。MySQL中的全文索引類型爲FULLTEXT的索引。  FULLTEXT 索引僅可用於 MyISAM表;

複製代碼 代碼如下:


CREATE TABLE articles (
   id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
   title VARCHAR(200),
   body TEXT,
   FULLTEXT (title,body)
    );


mysql> SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('database');

查詢結果:
+----+-------------------+------------------------------------------+
| id | title             | body                                     |
+----+-------------------+------------------------------------------+
|  5 | MySQL vs. YourSQL | In the following database comparison ... |
|  1 | MySQL Tutorial    | DBMS stands for DataBase ...             |
+----+-------------------+------------------------------------------+
2 rows in set (0.00 sec)
MATCH()函數對於一個字符串執行資料庫內的自然語言搜索。一個資料庫就是1套1個或2個包含在FULLTEXT內 的列。搜索字符串作爲對AGAINST()的參數而被給定。對於表中的每一行, MATCH() 返回一個相關值,即, 搜索字符串和 MATCH()表中指定列中該行文字之間的一個相似性度量
(5)複合索引

代碼如下:

CREATE TABLE test (
    id INT NOT NULL,
    last_name CHAR(30) NOT NULL,
    first_name CHAR(30) NOT NULL,
    PRIMARY KEY (id),
    INDEX name (last_name,first_name)
);


name索引是一個對last_name和first_name的索引。索引可以用於爲last_name,或者爲last_name和first_name在已知範圍內指定值的查詢。因此,name索引用於下面的查詢:
SELECT * FROM test WHERE last_name='Widenius';
SELECT * FROM test WHERE last_name='Widenius' AND first_name='Michael';
但是不能用於SELECT * FROM test WHERE first_name='Michael';這是因爲MySQL組合索引爲“最左前綴”的結果,簡單的理解就是隻從最左面的開始組合。

3.在什麼情況下使用索引
(1)爲搜索字段建索引,如果在你的表中,某個字段你經常用來做搜索,那麼,請爲其建立索引吧。一般來說,在WHERE和JOIN中出現的列需要建立索引以提高查詢速度。
例如從fps表(表中有name字段)中檢索姓名爲"李武"的人,
下面用explain來解釋執行建立索引和未建立索引的區別:

a.未建立索引前

代碼如下:


explain select name from fps where name="李武";



[SQL] select name from fps where name="李武";
影響的數據欄: 0
時間: 0.003ms
b.建立索引後

複製代碼 代碼如下:


create index idx_name on fps(
name
);


explain select name from fps where name="李武";

[SQL] select name from fps where name="李武";

影響的數據欄: 0
時間: 0.001ms

(2)下面我們就來看看這個EXPLAIN分析結果的含義。
table:這是表的名字。
type:連接操作的類型。下面是MySQL文檔關於ref連接類型的說明:
“對於每個來自於前面的表的行組合,所有有匹配索引值的行將從這張表中讀取。如果聯接只使用鍵的最左邊的前綴,或如果鍵不是
UNIQUE或PRIMARY KEY(換句話說,如果聯接不能基於關鍵字選擇單個行的話),則使用ref。如果使用的鍵僅僅匹配少量行,該聯接
類型是不錯的。” 在本例中,由於索引不是UNIQUE類型,ref是我們能夠得到的最好連接類型。 如果EXPLAIN顯示連接類型是“ALL”,而且你並不想從表裏面選擇出大多數記錄,那麼MySQL的操作效率將非常低,因爲它要掃描整個表。你可以加 入更多的索引來解決這個問題。預知更多信息,請參見MySQL的手冊說明。
possible_keys:
可能可以利用的索引的名字。這裏的索引名字是創建索引時指定的索引暱稱;如果索引沒有暱稱,則默認顯示的是索引中第一個列的名字
(在本例中,它是“idx_name”)。
Key:
它顯示了MySQL實際使用的索引的名字。如果它爲空(或NULL),則MySQL不使用索引。
key_len:
索引中被使用部分的長度,以字節計。
ref:
它顯示的是列的名字(或單詞“const”),MySQL將根據這些列來選擇行。在本例中,MySQL根據三個常量選擇行。
rows:
MySQL所認爲的它在找到正確的結果之前必須掃描的記錄數。顯然,這裏最理想的數字就是1。 本例中未索引前遍歷的記錄數爲1041,而建立索引後爲1
Extra:
這裏可能出現許多不同的選項,其中大多數將對查詢產生負面影響。在本例中,MySQL只是提醒我們它將用using where,using index子句限制搜索結果集。

4.最常用的存儲引擎:
(1)Myisam存儲引擎:
每個Myisam在磁盤上存儲成三個文件。文件名都和表名相同,擴展名分別爲.frm(存 儲表定義)、.MYD(存儲數據)、.MYI(存儲索引)。數據文件和索引文件可以放置在不同目錄,平均分佈io,獲得更快的速度。對存儲大小沒有限 制,MySQL數據庫的最大有效表尺寸通常是由操作系統對文件大小的限制決定的,
(2)InnoDB存儲引擎:具有提交、回滾、奔潰恢復能力的事務安全。與Myisam相比,InnoDB的寫效率差一些並且會佔用更多的磁盤空間以保留數據和索引。
(3)如何選擇合適的引擎
下面是常用存儲引擎適用的環境:
Myisam:它是在Web、數據倉儲和其他應用環境下最常使用的存儲引擎;
InnoDB:用於事務處理應用程序,具有更多特性,包括ACID事務特性。

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