數據庫的索引詳解

索引的重要性:當你的數據庫的性能出現問題了,那麼就重新優化你的索引吧,這能夠解決80%的性能問題,由此可見索引的重要性,尤其在數據量越來越大的時候,影響更加的明顯,一個最優的索引能夠輕易的將查詢性能提高好幾個數量級

索引的作用和優點:
1. 能夠大大的提高數據的查詢檢索速度
2. 通過創建唯一性索引可以保證數據庫中每一行的唯一性
3. 可以加速表和表之間的連接,特別是在實現數據的參考完整性方面特別有意義。
4. 在使用分組和排序子句進行數據檢索時,同樣可以顯著減少查詢中分組和排序的時間。
5. 通過使用索引,可以在查詢的過程中,使用查詢優化器,提高系統的性能。
索引的弊端和缺點:
1. 索引會佔用一部分存儲空間,尤其在數據量很大的時候佔用的存儲空間可是很客觀的;
2. 一旦對數據進行了插入、刪除、修改等操作,要對索引進行動態的維護。

但是總的來說利還是大於弊的,所以我們設計數據庫的時候需要善於利用索引,善於優化索引。

索引是最好的提高查詢解決方案嗎?
答案: 不一定,只有當索引幫助存儲引擎快速查找帶來的好處大於其帶來的額外開銷時,索引纔是有效的。
對於非常小的表,大部分情況下全表掃描更加有效
對於大中型的表,索引非常有效
對於特大型的表,建立和維護索引的代價特別大,索引就不是那麼有效了,可以使用分區技術,來進行一組數據的查詢(而不是一條一條的匹配),對於更大的TB級別的數據,經常會使用塊級別的元數據技術來代替索引,例如Infobright

什麼地方該用索引,什麼地方應該避免使用索引?
使用索引:
1. 在數據量超過幾百行之後就應該考慮建立索引,在主鍵上建立索引,保證數據的唯一性和組織表中的數據排列結構
2. 在經常使用到的查詢列上建立索引,比如 where name = “wang” ,經常做這樣的查詢,那麼name上就應該建立索引
3. 在經常進行範圍查詢的列上建立索引(可以建立聚簇索引,讓索引的順序和數據的物理存放順序一致,這樣大大的加快的查找的速度,變隨機查找爲順序查找)
4. 在經常用在連接的列上,在連接字段列上建立索引,這些列主要是一些外鍵,可以加快連接的速度;
5. 在經常需要排序的列上創建索引,因爲索引已經排序,這樣查詢可以利用索引的排序,加快排序查詢時間;
不該使用索引
1. 數據量太小不要建立索引,因爲維護的代價要高於建立索引之後優化的代價
2. 經常頻繁更新的列不要建立索引,因爲一旦更新,就要對索引也要隨之更新,如果更新的代價比查詢的代價高,那就不要建立索引
3. 不經常被引用、查詢的列不要建立索引,因爲沒有必要
4. 對於那些列的取值很少(比如性別),或者text等類型的大文本字段不要建立索引,大文本字段的索引也會很長,影響查詢

使用索引注意事項:
1. 對於複合索引,要選擇合適的順序建立索引,因爲對於mysql來說,建立了字段 (A,B,C)的複合索引,其實實質上是建立了 索引 A,B,C 和索引A, 所以當你單獨用 B 和C去查詢的時候,索引並沒有用到.
在這裏特別需要注意的是:索引的順序非常重要!!!{
不過不是按照索引的最左列開始查找,則無法使用索引, B 和C 不行
不能跳過索引中的列, 利用A C查詢無法使用索引
如果查詢中有某個列的範圍,則右邊的列無法使用索引查詢優化,
}
2. order by中的列是不會使用索引的, 對於索引列排序, MySQL查詢只使用一個索引,因此如果where子句中的列已經使用了索引的話,在數據庫默認排序可以符合要求的情況下不要使用排序操作,所以如果可以的話,在經常order by的列上建立索引
3. 一般情況下不鼓勵使用like操作,如果非使用不可,如何使用也是一個問題。like “%aaa%” 不會使用索引,而like “aaa%”可以使用索引。
4. 不要在列上進行計算,因爲一旦出現了計算操作,將會導致該列不使用索引,而是直接全表掃描。
5. 一些sql語句會導致不使用索引,而進行全表掃描,應該避免,比如:
where 子句中不要對字段進行 null 值判斷,否則將導致引擎放棄使用索引而進行全表掃描:select id from t where num is null (全表掃描) 修改成 select id from t where num is 0;
where 字句中不要使用!=或<>操作符,否則將導致引擎放棄使用索引而進行全表掃描
where 子句中不要使用 or 來連接條件,否則將導致引擎放棄使用索引而進行全表掃描,應該修改爲使用 union 或者 union all (這兩者的區別是 union 返回的是不重複的值,而union all 返回所有的每一列的值,包含重複元素 )
select id from t where num=10 or num=20 全表掃描
可以替換成:
select id from t where num=10
union all
select id from t where num=20
in 和 not in 也要慎用,否則會導致全表掃描 建議能用between替換,建議使用between, 另外用exists 替換也是很好的
select num from a where num in(select num from b)
用下面的語句替換:
select num from a where exists(select 1 from b where num=a.num)
注意的是 exists 實際上並不返回值,它只是檢查exists 裏面是否至少返回了一行數據,你可以理解爲它返回一個true 或者false, 如果是那麼where 語句就成立, 所以select 1你可以寫成select 2,select id 都是沒有任何問題的, 而in 確實會返回結果集的,所以in() 裏面的字句必須返回的是num 字段集
在列上對字段進行表達式操作,計算操作,函數操作,和使用參數都會導致全表掃描

索引根據其構造結構可以分爲 : B-tree索引, B+tree索引, Hash索引全文索引,空間數據索引(R-Tree),分行樹索引(TokuDB中使用)
先介紹幾種樹的概念:
B樹是二叉的排序樹,也叫二叉查找樹
紅黑樹是B樹的變種,是平衡的二叉排序樹
B-Tree 也是B樹的改進,而不過二叉變成了多叉,而且非葉子節點中也存儲了數據,搜索有可能到非葉結點就結束。
B+Tree 是B-tree的變種,所有的關鍵字都出現在葉子節點上,一次查找搜索必然是到葉子節點上才結束的。
B-tree 索引:
B-tree 是一種平衡的多叉排序樹,,,B-Tree它的特點如下:(M代表着階數,代表着一個節點最多有多少個孩子節點,例如M階B樹代表着該B樹的節點的孩子節點最多有M個
1.定義任意非葉子結點最多隻有M個兒子;且M>2;
2.根結點的兒子數爲[2, M];
3.除根結點以外的非葉子結點的兒子數爲[M/2, M];
4.每個結點存放至少M/2-1(取上整)和至多M-1個關鍵字;(至少2個關鍵字)
5 非葉子節點的關鍵字個數 = 指向兒子的指針個數 - 1
6. 非葉子結點的指針:P[1], P[2], …, P[M];其中P[1]指向關鍵字小於K[1]的子樹,P[M]指向關鍵字大於K[M-1]的子樹,其它P[i]指向關鍵字屬於(K[i-1], K[i])的子樹
7. 所有的葉子節點位於同一層

B-Tree的特性:
1. 關鍵字集合分佈在整棵樹中
2. 任何關鍵字出現且只出現在一個節點中
3. 搜索有可能在非葉子節點中結束
4. 搜索性能等價於做二分查找,做一次查找最大的次數爲 h 次,h爲B-tree的深度

在數據庫中B-Tree索引的實現:
1. 根節點常駐內存
2. 根節點和非葉子節點的槽中存放了指向下一個子節點的指針,每個頁中存放着一些關鍵字,與指針相對應,定義了子節點中值的上限與下限,存儲引擎根據這些指針向下層查找, 但是葉子節點中只存放數據的物理地址,不再存放指針。
3. 將每一個節點設定爲一個頁的大小,這樣只需要一次I/O就可以讀取一個節點的內容,(這是因爲頁是計算機管理存儲器的邏輯塊,硬件和操作系統在進行內存和磁盤上的數據交換時往往以一個頁作爲基本單位)
4. 在葉節點和非葉子節點中,都存儲了關鍵字(該關鍵字裏包含了指向該索引數據本身的物理地址),在一次查找中,給定了某個關鍵字,如果在任何節點找到了該關鍵字(包括非葉結點)則就可以根據找到的關鍵字讀取到該關鍵字所指向的實際數據。

B+tree 索引: 是B-Tree的變種
大部分的定義和B-Tree相同,但是它有獨特於B-tree的地方,
1. 非葉結點的子樹指針和關鍵字個數相同
2. 非葉子結點的子樹指針P[i],指向關鍵字值屬於[K[i], K[i+1])的子樹(B-樹是開區間)
3. 所有的葉子節點增加了一個指針,指針指向相鄰的葉子節點。
4. 所有的關鍵字都在葉子節點中出現

B+Tree的特點
1. 所有的關鍵字都出現在葉子節點中(稠密索引),而且葉子節點中的關鍵字恰好都是有序的
2. 不可能在非葉子節點查找成功,這是因爲非葉子節點中存儲的仍舊是索引,並沒有存儲實際的數據或者指向實際數據的物理地址,在葉子節點才存放的是實際的數據或者實際數據的物理地址
3. 查找方式有兩種: 一種是從根節點進行查找,另一種是可以從葉子節點的開頭開始查找,因爲葉子節點中存儲了指向下一個葉子節點的指針,而且在數據庫的實現中,葉子節點在實際的物理存儲中是順序存放的,也就是葉子節點都是集中在一塊存儲區域內存放的(這樣的好處是大大提高了區間查詢效率)
4. 更適合文件系統

B+Tree 在 MySQL中的實現
MySQL 中 的 InnoDB和MyISAM存儲引擎使用的就是B+Tree的實現方案
在InnoDB中,數據的物理存放順序是按照設定聚簇索引的列的順序進行組織的(實質上是按照主鍵的順序組織數據),聚簇索引(一定包含主鍵,但也可能是主鍵和其他列的複合索引),對於InnoDB中來說,它的索引文件和數據文件是同一個文件,所以讀取進來的頁中(也就是一個節點)包含了key和data(key 爲索引,data爲實際的數據)
{
同時,對於聚簇索引來說, key = 索引鍵值;data = 實際數據本身
對於非聚簇索引,key = 索引鍵值, data = 聚簇索引的值
}
所以瞭解了InnoDB的索引實現就可以很容易的理解爲什麼不建議使用過長的字段作爲主鍵,因爲所有輔助索引都引用主索引,過長的主索引會令輔助索引變得過大另外使用自增字段作爲主鍵則是一個很好的選擇,因爲非遞增的索引會在插入刪除數據時候,爲了維持B+Tree的特性而頻繁的進行調整,十分低效

對於MyISAM 存儲引擎,按主鍵順序儲存數據,索引文件和數據文件是兩個文件,會將索引文件讀進內存,文件中的所有索引, key = 索引鍵值, data = 數據的物理地址 。

MyISAM 和InnoDB中的索引比較
1. MyisAM支持全文索引(FULLTEXT)、壓縮索引,InnoDB不支持
2. MyisAM 按主鍵順序儲存數據,主鍵索引葉子節點保存對應數據行物理地址,輔助索引跟主鍵索引相差無幾;InnoDB 按聚簇索引順序存儲數據,聚簇索引同時保存數據行實際數據,其他輔助索引保存的是聚簇索引的值
3. MyisAM鍵值分離,索引載入內存(key_buffer_size),數據緩存依賴操作系統; InnoDB鍵值一起保存,索引與數據一起載入InnoDB緩衝池; MyisAM主鍵(唯一)索引按升序來存儲存儲,InnoDB則不一定
4. MyisAM處理字符串索引時用增量保存的方式,如第一個索引是‘preform’,第二個是‘preformence’,則第二個保存是‘7,ance’,這個明顯的好處是縮短索引,但是缺陷就是不支持倒序提取索引,必須順序遍歷獲取索

B+Tree 和B-Tree的性能比較?
1. 相對來說 ,B-Tree鍵值只在索引中出現一次,比B+Tree能節省存儲空間
2. B-Tree樹的鍵值位置不定,使得在插入刪除操作中複雜度明顯增加,B+Tree的插入刪除操作性能比B-Tree更好
3. B+Tree因爲葉子節點的物理存放是集中在一塊存儲區域的而且按順序存放,所以 B+Tree進行區間查詢的速度會更加的快

先介紹一下局部性原理和磁盤預讀:
局部性原理: 當一個數據被用到時,其附近的數據也通常會馬上被使用。程序運行期間所需要的數據通常比較集中
磁盤預讀(目的就是要減少磁盤I/O,理論根據就是局部性原理): 由於存儲介質的特性,磁盤本身存取就比主存慢很多,再加上機械運動耗費,磁盤的存取速度往往是主存的幾百分分之一,因此爲了提高效率,要儘量減少磁盤I/O。爲了達到這個目的,磁盤往往不是嚴格按需讀取,而是每次都會預讀,即使只需要一個字節,磁盤也會從這個位置開始,順序向後讀取一定長度的數據放入內存。
由於磁盤順序讀取的效率很高(不需要尋道時間,只需很少的旋轉時間),因此對於具有局部性的程序來說,預讀可以提高I/O效率。
預讀的長度一般爲頁(page)的整倍數。頁是計算機管理存儲器的邏輯塊,硬件及操作系統往往將主存和磁盤存儲區分割爲連續的大小相等的塊,每個存儲塊稱爲一頁(在許多操作系統中,頁得大小通常爲4k),主存和磁盤以頁爲單位交換數據。當程序要讀取的數據不在主存中時,會觸發一個缺頁異常,此時系統會向磁盤發出讀盤信號,磁盤會找到數據的起始位置並向後連續讀取一頁或幾頁載入內存中,然後異常返回,程序繼續運行

爲什麼選用B+/-Tree,而不是用紅黑樹(平衡二叉樹)?
上面介紹了在索引的實現中,是將每一個節點設置爲一個頁的大小來提高效率的,可知檢索一次最多需要訪問h個節點,需要h-1次磁盤I/O,O(h)=O(logdN)。一般實際應用中,出度d是非常大的數字,通常超過100,因此h非常小(通常不超過3)。
如果使用紅黑樹構件索引,那麼樹的深度H將會非常的大,O(h)=O(log2N),由於邏輯上很近的節點(父子)物理上可能很遠,無法利用局部性,所以紅黑樹的I/O需要h-1次,效率明顯比B-Tree差很多。

B-Tree的插入與刪除請觀看博客
http://blog.csdn.net/hguisu/article/details/7786014

插入:首先在最底層的節點中添加一個關鍵字,如果添加該關鍵字之後,滿足M階B樹的條件(該節點關鍵字個數不超過M-1),則完成添加,否則就要對B樹進行調整,具體的調整策略請看上面鏈接的博客。
刪除的時候,首先在最底層的節點刪除那個關鍵字,刪除之後,看是否滿足M階B樹的條件(關鍵字數目不低於ceil(M/2) 向上取整),滿足刪除成功,不滿足對樹進行調整,調整策略請看上述博客。

Hash索引:
基於Hash表實現,只有精確匹配索引所有列的查詢纔會生效。
Hash索引的優勢:
對於每一行,存儲索引都會對所有的索引計算一個hash值,該值比較小,hash索引將每一行對應的hash值存儲在hash索引中,也就是說hash表中存放了每一行的hash值,和該行的數據地址, 因此索引的結構非常緊湊,節省了存儲空間,同時hash索引的查詢速度非常的快
Hash索引的侷限:
1. hash索引只包含哈希值和行指針,而不存儲字段值,所以必須要實現讀取行數據本身的操作
2. hash索引不能用來進行範圍查詢(like,< >等),只支持等值查詢
3. hash索引也無法用來進行排序,因爲它不是按照索引值的大小進行存儲的
4. 對於複合索引,不支持部分索引列匹配查找,比如在A,B,C上建立索引(hash值爲ABC的聯合值),所以單獨查詢A無法使用Hash索引
5. 如何hash衝突很多的話,代價也比較大

全文索引
是一種特殊類型的索引,它查找的是文本中的關鍵詞,而不是直接比較索引中的值,類似於搜索引擎做的事情。
MyISAM中的全文索引是一類特殊的B-Tree索引,共有兩層,第一層是所有的關鍵字,對於每一個關鍵字的第二層包含的是一組相關的文檔指針,全文索引不會索引文檔中的所有詞語,會根據相關規則過濾掉一些詞語,而且也不會存儲關鍵字具體匹配在哪一行。
因爲MyISAM存儲引擎的限制,多數情況下我們會選擇InnoDB引擎 和 Sphinx插件來實現全文索引的功能。

按照功能來劃分: 索引可以分爲兩大類:
主鍵索引,在主鍵上建立的索引,不允許空值null,每一行都是唯一的,一個表只有一個主鍵,主鍵可以作爲外鍵
定義了主鍵,會自動的爲主鍵創建索引;
唯一索引,索引的字段的值只能出現一次,可以爲null,主鍵索引就是一種特殊的唯一索引,可以創建多個唯一索引
CREATE UNIQUE INDEX index_name
ON table_name (column_name)
普通索引(簡單索引)”允許使用重複的值,允許創建多個簡單索引
CREATE INDEX index_name
ON table_name (column_name);
複合索引,在多個列上建立的索引
CREATE INDEX index_name
ON table_name (column_name, column_name,….)
前綴索引: 單列的前10個字符創建前綴索引,前綴索引用於解決要索引一個很長的字符列的情況,訣竅是選擇合適長的前綴來保證較高的選擇性(利用前綴就可以精確定位到一行要查詢的數據),又不會太長造成創建或者維護索引的巨大開銷。MySQL中對於Blob,Text,很長的varchar的列必須使用前綴索引
CREATE INDEX index_name
ON table_name (column_name(10));
在創建表的時候創建主鍵索引,唯一索引,普通索引:
CREATE TABLE IF NOT EXISTS ‘User’ (
PRIMARY KEY (id),
UNIQUE KEY forumid (forumid),
KEY forumname (forumname),
KEY realname (realname)

聚簇索引(聚集索引)
CREATE CLUSTERED INDEX index_name
ON table_name (column_name);
非聚簇索引:除聚簇索引外的其他索引都是非聚簇索引。

下面詳細的介紹一下聚簇索引。
聚簇索引實質上是一種數據的存儲方式,它將數據行和相鄰的索引鍵值緊湊的存儲在一起,所以一個表只能有一個聚簇索引,因爲不可能將數據存放在兩個位置。數據的物理存放順序和索引的存放順序是一致的。
MySQL中InnoDB的聚簇索引的實現,對於InnoDB來說,該存儲引擎默認以主鍵作爲聚簇索引來組織存儲數據,所以InnoDB無法顯式的創建聚簇索引了。因此InnoDB如果沒有定義主鍵,會選擇一個唯一的非空索引代替,如果這也沒有,會隱式的定義一個主鍵來作爲聚簇索引。
聚簇索引的優點:
1. 把相關的數據保存在一起,減少了磁盤的I/O操縱
2. 數據的訪問更加快捷,它將索引和數據保存在一起,因此只要找到了索引值就找到了數據,不需要再次去讀取。
3. 使用覆蓋索引掃描的查詢可以直接使用節點中的主鍵值。
聚簇索引的缺點:
1. 聚簇索引的最大優勢是減少了磁盤I/O和查詢數據的時間,如果數據全部在內存,則優勢很微弱了
2. 插入速度嚴重依賴於插入順序,按照主鍵的插入順序是加載數據到InnoDb表中速度最快的方式(而且主鍵最好設置爲一個自增的字段,這樣主鍵的值是順序的,每次在插入的時候都能夠插入到表的最後面,如果主鍵不是自增的,那麼在插入的時候新的行不一定比最後的一行的鍵值大,所以總需要爲新的行尋找合適的位置,需要額外工作,這也是爲什麼建議使用自增主鍵的原因),但是也會產生問題,對於高併發的工作環境中,在InnoDB中按照主鍵順序插入到表中會造成明顯的鎖的爭用,因爲有可能所有的插入操作都集中在主鍵的上界點,導致插入所需的間隙鎖的競爭,或者增加一行數據,所有的插入操作集中在主鍵的下界點。
3. 更新聚簇鎖的代價很大,因爲也要移動數據
4. 會導致全表掃描變慢,尤其是行很稀疏或者由於頁分裂導致數據存放不連續的時候
5. 在InnoDB中,二級索引可能比想象中的更大,而且二級索引需要兩次查詢才能命中數據這是因爲二級索引中存放的是主鍵的值,而不是指向行的物理地址。(二級索引之所以如此設計的原因是在InnoDB表中的數據進行了移動行或者數據也分裂時無需更新二級索引的這個指針)

覆蓋索引:如果一個索引中已經包含(或者說覆蓋了)所有要查詢的字段的值,我們就稱之爲覆蓋索引,這樣就可以直接使用索引來直接獲取列的數據,而不再需要讀取數據行的回表查詢了。善用覆蓋索引能提高查詢速度。

explain 解析器: 分析sql語句的查詢性能情況,分析select的查詢行爲
關於這個解釋器參數的詳細說明,可以參考博客
http://blog.csdn.net/leileixiaoshan/article/details/26108427

我在這裏只做一個簡要的概括說明:
id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+—-+————-+————–+——+—————+——+———+——+———+————-+
| 1 | SIMPLE | TradeBalance | ALL | NULL | NULL | NULL | NULL | 3418948 | Using where

id:表示查詢語句中的查詢順序(select 語句中可能有子查詢),id越大,說明越早執行

select_type: 每個select字句的查詢類型, 簡單或者複雜,
SIMPLE: 代表不包含子查詢或者Union
PRIMARY,SUBQUERY 包含子查詢,最外層的標記爲PRIMARY ,子查詢標記爲SUBQUERY
UNION:第二個select語句出現在Union之後,標記爲Union
DERIVED:在From列表中包含的子查詢
UNION RESULT:從UNION表獲取結果的SELECT

table: 查詢的表的名字

type(這個屬性很重要): 訪問類型,表示MySQL在表中找到所需行的方式, 從上到下,性能由最差到最好
ALL: 全表查詢,遍歷全表找到匹配行‘
index:利用索引進行索引的遍歷查詢
range 索引範圍掃描, 對索引的掃描開始於某一點,返回匹配的行,常見於between,<, >
ref: 非唯一性索引掃描, 返回匹配某個單獨值的所有行, 常見於 =
eq_ref: 唯一性索引掃描, 返回匹配的唯一一行,常見於主鍵或者唯一索引掃描
const、system,查詢對某部分進行優化,並且轉換爲一個常量時,system表示查詢的表只有一行的特殊情況
null: MySqL在優化過程中分解語句,執行甚至不用訪問表或者索引
possible_keys, 是指查詢可能使用到的索引,key,表示查詢實際使用到的索引, key_len表示索引字段可能的最大長度

ref: 上述表的連接匹配條件,即哪些列或常量被用於查找索引列上的值
rows: 找到所需的記錄所需要讀取的行數,也就是符合匹配條件的行數
Extra,額外的信息
Using index: 表示在select操作中用到了覆蓋索引(Covering index)
Using where: 表示MySqL使用where字句來過濾結果集,而且是先返回行結果集以後再使用where語句過濾行
Using temporary : 表示需要使用到臨時表來存儲結果集,常用於排序和分組
Using filesort 表示無法利用索引進行排序的操作稱爲文件排序
MySQL執行計劃的侷限

•EXPLAIN**不會告訴你關於觸發器、存儲過程的信息或用戶自定義函數對查詢的影響情況**
EXPLAIN不考慮各種Cache
EXPLAIN不能顯示MySQL在執行查詢時所作的優化工作
•部分統計信息是估算的,並非精確值
EXPALIN只能解釋SELECT操作,其他操作要重寫爲SELECT後查看執行計劃

高性能的索引策略要考慮如下方面:
1. 獨立的列,即查詢的的時候列中不存在計算,表達式,函數參數等
2. 對於索引長字符列(blob,Text,),善於使用前綴索引
3. 要選擇合適的索引順序,按照經驗來說,選擇性較高的字段放在前面,也就是說經過第一個條件之後得到的行數會比較的少
4. 善於使用聚簇索引,在innoDb中按照主鍵順序插入行
5. 善於利用覆蓋索引
6. 利用索引掃描來做排序
7. 可以使用壓縮索引
8. 移除或者優化重複和冗餘索引,對於未使用的索引要刪除掉
9. 索引和鎖,索引可以減少innoDB訪問行的行數,從而減少對行的加鎖,使用了索引之後,索引會過濾掉一些無效的行,從而使得只對有效的行進行加鎖,需要注意的是,有時即使使用了索引也會鎖住一些無效的行:
select id from user where id <5 and id >1; 有時對於這種範圍查詢的時候也會鎖住一些無效的行,首先結果會返回 id<5 的所有行,然後加鎖, 然後再從結果中找 >1的結果返回,然後再解鎖。
由此可見,如果不使用索引,就會對全表掃描而鎖住所有的行,開銷特別大。

此博文參考了博客
http://blog.csdn.net/superhosts/article/details/25611119
http://blog.csdn.net/leileixiaoshan/article/details/26108427

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