亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 數據庫 > 文庫 > 正文

數據庫為何要建立索引的原因說明

2020-10-29 21:52:36
字體:
來源:轉載
供稿:網友
這里想把之前的索引學習筆記總結一下:

    首先明白為什么索引會增加速度,DB在執行一條Sql語句的時候,默認的方式是根據搜索條件進行全表掃描,遇到匹配條件的就加入搜索結果集合。如果我們對某一字段增加索引,查詢時就會先去索引列表中一次定位到特定值的行數,大大減少遍歷匹配的行數,所以能明顯增加查詢的速度。那么在任何時候都應該加索引么?這里有幾個反例:1、如果每次都需要取到所有表記錄,無論如何都必須進行全表掃描了,那么是否加索引也沒有意義了。2、對非唯一的字段,例如“性別”這種大量重復值的字段,增加索引也沒有什么意義。3、對于記錄比較少的表,增加索引不會帶來速度的優化反而浪費了存儲空間,因為索引是需要存儲空間的,而且有個致命缺點是對于update/insert/delete的每次執行,字段的索引都必須重新計算更新。

    那么在什么時候適合加上索引呢?我們看一個Mysql手冊中舉的例子,這里有一條sql語句:

    SELECT c.companyID, c.companyName FROM Companies c, User u WHERE c.companyID = u.fk_companyID AND c.numEmployees >= 0 AND c.companyName LIKE '%i%' AND u.groupID IN (SELECT g.groupID FROM Groups g WHERE g.groupLabel = 'Executive')

    這條語句涉及3個表的聯接,并且包括了許多搜索條件比如大小比較,Like匹配等。在沒有索引的情況下Mysql需要執行的掃描行數是 77721876行。而我們通過在companyID和groupLabel兩個字段上加上索引之后,掃描的行數只需要134行。在Mysql中可以通過 Explain Select來查看掃描次數??梢钥闯鰜碓谶@種聯表和復雜搜索條件的情況下,索引帶來的性能提升遠比它所占據的磁盤空間要重要得多。

    那么索引是如何實現的呢?大多數DB廠商實現索引都是基于一種數據結構――B樹。因為B樹的特點就是適合在磁盤等直接存儲設備上組織動態查找表。B樹的定義是這樣的:一棵m(m>=3)階的B樹是滿足下列條件的m叉樹:

    1、每個結點包括如下作用域(j, p0, k1, p1, k2, p2, ... ki, pi) 其中j是關鍵字個數,p是孩子指針

    2、所有葉子結點在同一層上,層數等于樹高h

    3、每個非根結點包含的關鍵字個數滿足[m/2-1]<=j<=m-1

    4、若樹非空,則根至少有1個關鍵字,若根非葉子,則至少有2棵子樹,至多有m棵子樹

    看一個B樹的例子,針對26個英文字母的B樹可以這樣構造:

    可以看到在這棵B樹搜索英文字母復雜度只為o(m),在數據量比較大的情況下,這樣的結構可以大大增加查詢速度。然而有另外一種數據結構查詢的虛度比B樹更快――散列表。Hash表的定義是這樣的:設所有可能出現的關鍵字集合為u,實際發生存儲的關鍵字記為k,而|k|比|u|小很多。散列方法是通過散列函數h將u映射到表T[0,m-1]的下標上,這樣u中的關鍵字為變量,以h為函數運算結果即為相應結點的存儲地址。從而達到可以在o(1)的時間內完成查找。
    然而散列表有一個缺陷,那就是散列沖突,即兩個關鍵字通過散列函數計算出了相同的結果。設m和n分別表示散列表的長度和填滿的結點數,n/m為散列表的填裝因子,因子越大,表示散列沖突的機會越大。
    因為有這樣的缺陷,所以數據庫不會使用散列表來做為索引的默認實現,Mysql宣稱會根據執行查詢格式嘗試將基于磁盤的B樹索引轉變為和合適的散列索引以追求進一步提高搜索速度。我想其它數據庫廠商也會有類似的策略,畢竟在數據庫戰場上,搜索速度和管理安全一樣是非常重要的競爭點。


基本概念介紹:


索引

使用索引可快速訪問數據庫表中的特定信息。索引是對數據庫表中一列或多列的值進行排序的一種結構,例如 employee 表的姓(lname)列。如果要按姓查找特定職員,與必須搜索表中的所有行相比,索引會幫助您更快地獲得該信息。

索引提供指向存儲在表的指定列中的數據值的指針,然后根據您指定的排序順序對這些指針排序。數據庫使用索引的方式與您使用書籍中的索引的方式很相似:它搜索索引以找到特定值,然后順指針找到包含該值的行。

在數據庫關系圖中,您可以在選定表的“索引/鍵”屬性頁中創建、編輯或刪除每個索引類型。當保存索引所附加到的表,或保存該表所在的關系圖時,索引將保存在數據庫中。有關詳細信息,請參見創建索引。

注意;并非所有的數據庫都以相同的方式使用索引。有關更多信息,請參見數據庫服務器注意事項,或者查閱數據庫文檔。

作為通用規則,只有當經常查詢索引列中的數據時,才需要在表上創建索引。索引占用磁盤空間,并且降低添加、刪除和更新行的速度。在多數情況下,索引用于數據檢索的速度優勢大大超過它的。

索引列

可以基于數據庫表中的單列或多列創建索引。多列索引使您可以區分其中一列可能有相同值的行。

如果經常同時搜索兩列或多列或按兩列或多列排序時,索引也很有幫助。例如,如果經常在同一查詢中為姓和名兩列設置判據,那么在這兩列上創建多列索引將很有意義。

確定索引的有效性:

  • 檢查查詢的 WHERE 和 JOIN 子句。在任一子句中包括的每一列都是索引可以選擇的對象。
  • 對新索引進行試驗以檢查它對運行查詢性能的影響。
  • 考慮已在表上創建的索引數量。最好避免在單個表上有很多索引。
  • 檢查已在表上創建的索引的定義。最好避免包含共享列的重疊索引。
  • 檢查某列中唯一數據值的數量,并將該數量與表中的行數進行比較。比較的結果就是該列的可選擇性,這有助于確定該列是否適合建立索引,如果適合,確定索引的類型。
索引類型

根據數據庫的功能,可以在數據庫設計器中創建三種索引:唯一索引、主鍵索引和聚集索引。有關數據庫所支持的索引功能的詳細信息,請參見數據庫文檔。

提示:盡管唯一索引有助于定位信息,但為獲得最佳性能結果,建議改用主鍵或唯一約束。

唯一索引

唯一索引是不允許其中任何兩行具有相同索引值的索引。

當現有數據中存在重復的鍵值時,大多數數據庫不允許將新創建的唯一索引與表一起保存。數據庫還可能防止添加將在表中創建重復鍵值的新數據。例如,如果在 employee 表中職員的姓 (lname) 上創建了唯一索引,則任何兩個員工都不能同姓。

主鍵索引

數據庫表經常有一列或列組合,其值唯一標識表中的每一行。該列稱為表的主鍵。

在數據庫關系圖中為表定義主鍵將自動創建主鍵索引,主鍵索引是唯一索引的特定類型。該索引要求主鍵中的每個值都唯一。當在查詢中使用主鍵索引時,它還允許對數據的快速訪問。

聚集索引

在聚集索引中,表中行的物理順序與鍵值的邏輯(索引)順序相同。一個表只能包含一個聚集索引。

如果某索引不是聚集索引,則表中行的物理順序與鍵值的邏輯順序不匹配。與非聚集索引相比,聚集索引通常提供更快的數據訪問速度。


建立方式和注意事項

最普通的情況,是為出現在where子句的字段建一個索引。為方便講述,我們先建立一個如下的表。

CREATE TABLE mytable (

 id serial primary key,

 category_id int not null default 0,

 user_id int not null default 0,

 adddate int not null default 0

);

如果你在查詢時常用類似以下的語句:

 SELECT * FROM mytable WHERE category_id=1;

最直接的應對之道,是為category_id建立一個簡單的索引:

 CREATE INDEX mytable_categoryid

 ON mytable (category_id);

OK.如果你有不止一個選擇條件呢?例如:

 SELECT * FROM mytable WHERE category_id=1 AND user_id=2;

你的第一反應可能是,再給user_id建立一個索引。不好,這不是一個最佳的方法。你可以建立多重的索引。

CREATE INDEX mytable_categoryid_userid ON mytable (category_id,user_id);

注意到我在命名時的習慣了嗎?我使用"表名_字段1名_字段2名"的方式。你很快就會知道我為什么這樣做了。

現在你已經為適當的字段建立了索引,不過,還是有點不放心吧,你可能會問,數據庫會真正用到這些索引嗎?測試一下就OK,對于大多數的數據庫來說,這是很容易的,只要使用EXPLAIN命令:

EXPLAIN

 SELECT * FROM mytable

WHERE category_id=1 AND user_id=2;

 This is what Postgres 7.1 returns (exactly as I expected)

 NOTICE: QUERY PLAN:

 Index Scan using mytable_categoryid_userid on

 mytable (cost=0.00..2.02 rows=1 width=16)

EXPLAIN

以上是postgres的數據,可以看到該數據庫在查詢的時候使用了一個索引(一個好開始),而且它使用的是我創建的第二個索引??吹轿疑厦婷暮锰幜税?,你馬上知道它使用適當的索引了。

接著,來個稍微復雜一點的,如果有個ORDER BY字句呢?不管你信不信,大多數的數據庫在使用order by的時候,都將會從索引中受益。

 SELECT * FROM mytable

WHERE category_id=1 AND user_id=2

 ORDER BY adddate DESC;

很簡單,就象為where字句中的字段建立一個索引一樣,也為ORDER BY的字句中的字段建立一個索引:

 CREATE INDEX mytable_categoryid_userid_adddate

 ON mytable (category_id,user_id,adddate);

 注意: "mytable_categoryid_userid_adddate" 將會被截短為

"mytable_categoryid_userid_addda"

 CREATE

 EXPLAIN SELECT * FROM mytable

WHERE category_id=1 AND user_id=2

 ORDER BY adddate DESC;

 NOTICE: QUERY PLAN:

 Sort (cost=2.03..2.03 rows=1 width=16)

-> Index Scan using mytable_categoryid_userid_addda

 on mytable (cost=0.00..2.02 rows=1 width=16)

 EXPLAIN

看看EXPLAIN的輸出,數據庫多做了一個我們沒有要求的排序,這下知道性能如何受損了吧,看來我們對于數據庫的自身運作是有點過于樂觀了,那么,給數據庫多一點提示吧。

為了跳過排序這一步,我們并不需要其它另外的索引,只要將查詢語句稍微改一下。這里用的是postgres,我們將給該數據庫一個額外的提示--在 ORDER BY語句中,加入where語句中的字段。這只是一個技術上的處理,并不是必須的,因為實際上在另外兩個字段上,并不會有任何的排序操作,不過如果加入,postgres將會知道哪些是它應該做的。

 EXPLAIN SELECT * FROM mytable

WHERE category_id=1 AND user_id=2

 ORDER BY category_id DESC,user_id DESC,adddate DESC;

 NOTICE: QUERY PLAN:

 Index Scan Backward using

mytable_categoryid_userid_addda on mytable

 (cost=0.00..2.02 rows=1 width=16)

 EXPLAIN

現在使用我們料想的索引了,而且它還挺聰明,知道可以從索引后面開始讀,從而避免了任何的排序。

以上說得細了一點,不過如果你的數據庫非常巨大,并且每日的頁面請求達上百萬算,我想你會獲益良多的。不過,如果你要做更為復雜的查詢呢,例如將多張表結合起來查詢,特別是where限制字句中的字段是來自不止一個表格時,應該怎樣處理呢?我通常都盡量避免這種做法,因為這樣數據庫要將各個表中的東西都結合起來,然后再排除那些不合適的行,搞不好開銷會很大。

如果不能避免,你應該查看每張要結合起來的表,并且使用以上的策略來建立索引,然后再用EXPLAIN命令驗證一下是否使用了你料想中的索引。如果是的話,就OK。不是的話,你可能要建立臨時的表來將他們結合在一起,并且使用適當的索引。

要注意的是,建立太多的索引將會影響更新和插入的速度,因為它需要同樣更新每個索引文件。對于一個經常需要更新和插入的表格,就沒有必要為一個很少使用的where字句單獨建立索引了,對于比較小的表,排序的開銷不會很大,也沒有必要建立另外的索引。

以上介紹的只是一些十分基本的東西,其實里面的學問也不少,單憑EXPLAIN我們是不能判定該方法是否就是最優化的,每個數據庫都有自己的一些優化器,雖然可能還不太完善,但是它們都會在查詢時對比過哪種方式較快,在某些情況下,建立索引的話也未必會快,例如索引放在一個不連續的存儲空間時,這會增加讀磁盤的負擔,因此,哪個是最優,應該通過實際的使用環境來檢驗。

在剛開始的時候,如果表不大,沒有必要作索引,我的意見是在需要的時候才作索引,也可用一些命令來優化表,例如MySQL可用"OPTIMIZE TABLE"。

綜上所述,在如何為數據庫建立恰當的索引方面,你應該有一些基本的概念了。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产一区二中文字幕在线看| 欧美激情性做爰免费视频| 久久天天躁狠狠躁夜夜爽蜜月| 成人情趣片在线观看免费| 久久久在线免费观看| 欧美性猛交xxxx偷拍洗澡| 亚洲国产精品小视频| 国产精品国产三级国产aⅴ浪潮| 日韩大片免费观看视频播放| 国产精品欧美一区二区| 欧美激情视频网站| 8050国产精品久久久久久| 久久久电影免费观看完整版| 亚洲一区二区三区四区视频| 岛国av一区二区在线在线观看| 亚洲欧洲视频在线| 久青草国产97香蕉在线视频| 欧美日韩aaaa| 久久中文精品视频| 国产在线久久久| 国产精品吊钟奶在线| 久热爱精品视频线路一| 欲色天天网综合久久| 欧美日韩国产丝袜另类| 久久久精品网站| 亚洲天堂av电影| 成人精品一区二区三区电影免费| 国产精品久久久久久久久久尿| 一本一道久久a久久精品逆3p| 色偷偷av一区二区三区| 久久久久久久一区二区三区| 亚洲最新av在线网站| 精品国内自产拍在线观看| 成人黄色影片在线| 国产suv精品一区二区三区88区| 国产丝袜高跟一区| 久久中文字幕国产| 欧美日韩在线视频一区二区| 自拍偷拍免费精品| 欧美老少做受xxxx高潮| 久久免费国产视频| 欧美大片在线免费观看| 97香蕉超级碰碰久久免费软件| 国产精品日韩在线一区| 国产精品爽爽ⅴa在线观看| 久久久女女女女999久久| 国产精品天天狠天天看| 91国内揄拍国内精品对白| 欧美刺激性大交免费视频| 欧美专区第一页| 国产91在线播放九色快色| 国产精品久久久久久久久免费| 欧美极度另类性三渗透| 亚洲日本欧美中文幕| 成人妇女免费播放久久久| 国产欧亚日韩视频| 国产一区二区免费| 日韩a**站在线观看| 国产精品第10页| 国产有码在线一区二区视频| 亚洲第一天堂av| 欧美精品情趣视频| 国产成人亚洲综合| 日本免费久久高清视频| 欧美成人午夜影院| 狠狠色狠色综合曰曰| 国产精品成人免费电影| 亚洲伊人一本大道中文字幕| 欧美成人免费全部观看天天性色| 91精品国产综合久久久久久蜜臀| 久久全球大尺度高清视频| 日韩小视频在线观看| 成人免费视频网| 国产亚洲精品美女久久久久| 久久伊人91精品综合网站| 久久久久久高潮国产精品视| 成人在线视频福利| 国产精品日韩专区| 精品成人国产在线观看男人呻吟| 国产成人精品电影久久久| 精品久久久久久久大神国产| 日韩在线观看免费网站| 欧美成人高清视频| 91高清视频在线免费观看| 久久6免费高清热精品| 国产成人精品一区| 日韩av快播网址| 欧美一级大片在线观看| 国产欧美日韩精品丝袜高跟鞋| 亚洲精品综合精品自拍| 欧美一区二区.| 色噜噜国产精品视频一区二区| 久久人人看视频| 91人人爽人人爽人人精88v| 欧美日韩高清在线观看| 日韩av中文字幕在线播放| 欧美最猛性xxxxx免费| 亚洲女同精品视频| 中文字幕精品视频| 欧日韩不卡在线视频| 夜夜嗨av一区二区三区免费区| 米奇精品一区二区三区在线观看| 18性欧美xxxⅹ性满足| 91av成人在线| 久久精品夜夜夜夜夜久久| 精品香蕉一区二区三区| 欧美激情免费看| 九九久久精品一区| 欧美性做爰毛片| 国产欧美一区二区三区久久人妖| 欧美在线观看www| 亚洲丝袜av一区| 欧美日韩国产在线看| 成人免费视频xnxx.com| www.日韩不卡电影av| 97国产精品免费视频| 欧美成人h版在线观看| 亚洲成人黄色网| 欧美高清电影在线看| 中文字幕亚洲在线| 视频在线一区二区| 国产精品福利在线观看| 日韩欧美一区二区三区久久| 亚洲qvod图片区电影| 日韩欧美在线免费观看| 国语自产偷拍精品视频偷| 国产suv精品一区二区三区88区| 国产精品激情av电影在线观看| 国产精品中文久久久久久久| 国产成人精品久久| 精品久久久久久| 成人久久18免费网站图片| 尤物99国产成人精品视频| 国产欧美婷婷中文| 欧美黑人xxxⅹ高潮交| 91精品久久久久久久久久另类| 亚洲精品综合精品自拍| 欧美日韩国产精品一区| 日韩av第一页| 亚洲va久久久噜噜噜久久天堂| 美日韩精品视频免费看| 欧美日韩国产123| 国内精品伊人久久| 一本色道久久88综合亚洲精品ⅰ| 91po在线观看91精品国产性色| 国产亚洲人成网站在线观看| 欧美精品久久久久久久免费观看| 日韩免费视频在线观看| 精品久久久久久久久国产字幕| 成人福利网站在线观看11| 中文字幕日韩精品在线观看| 亚洲国产美女精品久久久久∴| 国模gogo一区二区大胆私拍| 伊是香蕉大人久久| 亚洲精品欧美日韩| 2021国产精品视频| 国产精品久久久久av| 中文字幕免费精品一区| 欧美一级片在线播放| 亚洲天堂av女优| 亚洲aa在线观看| 欧美性视频网站| 91黑丝高跟在线| 4438全国成人免费|