如何利用索引提升性能

在關係數據庫中,表中數據廣泛以無序的狀態存儲在磁盤上,在沒有相應索引時,若要對錶中數據進行查詢,就只能全表檢索,將全部記錄挨個讀取,而後和查詢條件進行比較,顯然,這種方式會致使大量的磁盤 I/O 操做和 CPU 計算,消耗大量的系統時間,所以,創建索引就成了一個必須考慮的選項。mysql

使用 CREATE INDEX [索引名] on 表名 (列名,……) 語句能夠爲表中數據創建最經常使用的鍵值索引,而鍵值索引的實現大都採用 B+ 樹數據結構,它有如下一些性質:sql

一、 是一棵平衡樹,即從根節點到葉子節點的深度相差不超過 1;數據庫

二、 非葉子節點只保存鍵值和指向子節點的指針,不保存數據;數據結構

三、 葉子節點保存鍵值、對應記錄的地址及葉子節點的鏈表指針,鏈表中葉子節點是鍵值有序的app

但這些性質就必定能保證查詢性能知足用戶的需求嗎?下面,咱們以對銀行帳戶進行時間段查詢爲例,探討索引的性能問題。ide

爲了方便說明問題,咱們在這裏把 B+ 樹簡化爲 下圖所示的B+ 樹,以帳號和交易日期做爲鍵值,以下圖所示:性能

 

1558706168072100.png

若是咱們要查詢帳號 A002 從 2000-01-01 到 2000-01-07 的交易流水,數據庫系統會首先要查找帳號爲 A00二、日期不早於 2000-01-01 的鍵值所在的葉子節點,結果是依次讀取索引塊 A、B、C,而後找出索引塊 C 中知足條件的鍵值對應的記錄地址並讀出記錄返回,若索引塊 C 中最後一個日期早於或等於 2001-01-07,則能夠根據葉子節點的鏈表直接讀取索引列 D,以此類推,直到某個索引塊的某個日期比 2001-01-07 大爲止。fetch

觀察上述過程,咱們發現 2000-01-01 對應的記錄在數據頁 1,2000-01-02 和 2000-01-03 對應的記錄在數據頁 2,2000-01-04 對應的記錄則在數據頁 3,4 條記錄須要讀取 3 個數據頁,極端狀況下甚至任意一條記錄都在不一樣的數據頁,而此時若是數據區中記錄已按鍵值序存儲則能夠顯著減小磁盤 IO。更進一步,若是記錄數據直接保存在葉子節點,則能夠減小查詢過程當中索引頁與數據頁之間的跳讀,這對於機械硬盤的性能影響尤甚。指針

這些問題對於集算器的組表來講,能夠很是輕鬆地獲得解決。blog

咱們仍是以股票交易數據爲例講解組表的使用。


A
1 =file("d:/test/stktrade.ctx")
2 =A1.create@r(#sid,#tdate,open,close,volume)
3 =connect("mysql")
4 =A3.cursor("select   * from stktrade order by sid,tdate")
5 =A2.append(A4)
6 =A3.close()
7 =A2.index(idx1;sid,tdate)

A2: 建立數據結構爲 (sid,tdate,open,close,volume) 的組表,且指定 sid 和 tdate 爲鍵,@r 指定數據按行存儲

A5: 將按 sid 和 tdate 有序的數據追加到組表中

A6: 以 sid 和 tdate 爲鍵值創建索引 idx1


A
1 =file("d:/test/stktrade.ctx").create()
2 =A1.icursor(sid=="600036"   && tdate>=date("2018-01-01") &&   tdate<=date("2018-01-10"),idx1)
3 =A2.fetch()

A1: 讀取組表

A2: 定義根據索引 idx1 查詢數據的遊標

A3: 取出遊標中的數據

   在創建索引 idx1 時,也能夠將所需的數據都儲存在索引裏,譬如要將 open、close、volume 這 3 列也儲存在索引 idx1 裏,只需將前面表格裏的A2.index(idx1;sid,tdate)改成A1.index(idx1; sid,tdate; open,close,volume)便可,這樣查詢時就能夠不讀數據文件、只讀取索引文件,使查詢速度更快。

相關文章
相關標籤/搜索