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

http://blog.csdn.net/wxwzy738/article/details/17590305html

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

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

 

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 的組合各不相同。sql

  來看這條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 的更新速度。ide

  執行 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事務特性。

相關文章
相關標籤/搜索