mysql索引掃描


一 閒聊

由於之前一直接觸的都是mysql,從來沒有接觸過oracle數據庫,新公司用的就是oracle,先像着分析mysql一樣看一下oracle
強烈推薦大家看這麼書:《高性能MySQL第三版》

二 理論

首先我們使用count(1)進行查詢數據的總數:

	select count(1) from DATA_QC_IRREGULAR_DT

經過一段極其墨跡的時間,最終我們發現最終的執行時間達到了192秒,最終的數據總和是:38070178

在這裏插入圖片描述
因爲count(1)並沒有使用到對應表的主鍵進行檢索,所以,我們再去分析一下該表中存在的索引是有哪些
由於oracle中的表的索引並不是像mysql那樣,可以直接使用

show index from ‘table’

進行查詢,oracle中的索引信息是存放在user_indexes和user_ind_columns兩張表中,其中

在這裏插入圖片描述
oracle索引信息中user_ind_columns 表的字段解釋可以參考官方網站:https://docs.oracle.com/cd/E11882_01/server.112/e40402/statviews_1103.htm#REFRN20084

由上圖可知,該表是創建了一個NORMAL類型的索引,並且索引字JOB_QUEUE,DATA_TABLE_NAME,DATA_CONTENT_ID,RULE_ID
該庫建立的是一個組合索引,組合索引的列表爲(JOB_QUEUE,DATA_TABLE_NAME,DATA_CONTENTN_ID,RULE_ID)(由對應的COLUMN_POSITION可知)。

在mysql中,對於組合索引,是有一個最左前綴原則,即創建了(a,b,c)的組合索引,則已經對(a)(a,b)(a,b,c)(a,c)上建立索引
例如:

select tableColumn from 表名 where b = ’指定值‘ //不會走(a,b,c)這個組合索引
select tableColumn from 表名 where a = '指定值' and b = ’指定值‘ //會走(a,b,c)這個組合索引

在Oracle同樣也對組合索引有一個原則,但是Oracle對於組合索引的執行和mysql稍微不同:對於Oracle的組合索引有一個:INDEX SKIP SCAN(這個新的優化是針對Oracle9i版本之後)
     即組合索引的前導列(索引包含的第一列)沒有在查詢語句中出現,oracle也會利用該複合索引,這個時候就使用的INDEX SKIP SCAN

Oracle的索引掃描總計五種:

  • INDEX SKIP SCAN(索引跳躍掃描)
  • INDEX UNIQUE SCAN(索引唯一掃描)
  • INDEX RAGEN SCAN(索引範圍掃描)
  • INDEX FULL SCAN(索引全掃描)
  • INDEX FAST FULL SCAN(索引快速掃描)

INDEX RAGEN SCAN(索引範圍掃描)
針對索引範圍掃描,對於創建了組合索引的IND_IRREGULAR_DT(JOB_QUEUE,DATA_TABLE_NAME,DATA_CONTENTN_ID,RULE_ID)
執行:

select JOB_QUEUE from DATA_QC_IRREGULAR_DT where JOB_QUEUE = '12' and  DATA_TABLE_NAME = 'HT_CDM_VISITS'

即爲索引範圍掃描

INDEX UNIQUE SCAN索引唯一掃描
對於表 table1,如果創建了唯一索引id,執行以下sql語句

select id from test where id = 5000;

即爲索引唯一掃描,該索引掃描模式下是速度最快的
INDEX FULL SCAN索引全掃描
對於表來說,有全表掃描。對於索引來說,也存在全索引掃描,與全表掃描非常類似。索引掃描只在CBO模式下起作用。

什麼是CBO模式?這就不得不說Oracle的兩種優化器:
RBO:Rule-Based Optimization,Oracle 10g版本後被棄用,RBO是基於預先設定好的語法優先級對語法進行執行計劃的優化,所以開發者必須非常瞭解RBO的規則,這種方式非常呆板,因爲其只認規則。
CBO:Cost-Based Optimization,Oracle 8引入,Oracle 10g取代了RBO,根據SQL執行情況的統計信息來對SQL的執行計劃進行優化,這部分是Oracle公司保密的。問過Oracle公司的講師說也不清楚具體細節。

這種方式有個特點,會自動對數據進行排序。省去了全表掃描後,再進行order by的操作。
因爲B樹索引本身就是排序好的,默認是ASC升序,可以在創建索引的時候進行指定。但是Oracle的執行計劃會自動針對升序的降序查詢進行優化,那麼爲什麼要存在降序操作?答案是:在複合索引上,可以對(a desc,b asc),滿足一定的業務場景。

select * from test order by id;

因爲排序的條件只有id,並且id已經建立索引,所以執行計劃會被優化成INDEX FULL SCAN。
條件:表和表進行連接查詢,查詢語句中有order by,group by並且子句所有列都在索引中(聯合索引)

INDEX FAST FULL SCAN快速全表掃描
快速全表掃描是掃描索引中的所有數據塊,與全表掃描比,區別就是其不進行排序,即在這種方式下,返回的數據不是以排序的形式。可以多塊讀、並行讀。所以叫FAST。
對於表test,如果創建了(a,b)組合索引

select a,b from test where b<1000;

這個語句有兩個特點,第一:返回值a和b都在索引上,第二:查詢條件也在索引上。這條語句通過B樹索引查詢到rowid後,不需要額外在去原來的表裏查數據了。爲什麼呢?回憶一下,符合索引包括根、枝、葉,葉子上存儲的是索引值,包括:rowid、鍵值、鍵值長度、所屬標號。如果所取的值都在索引上,就可以直接返回了,如果是

select a,b,c from test where b<1000;

這樣返回值多了一個c,並不在複合索引上,所以還會用查到的rowid,去原表中取c的值,這樣就不會走INDEX FAST FULL SCAN了。

INDEX SKIP SCAN(索引跳躍掃描)
索引跳躍如面說的,如果對於一個表test,創建了(a,b)的組合索引,如果針對於a表,存在只取0或者1的情況下,oracle的優化器oracle的優化器會將其優化成兩個索引,分別是當a=0,a=1時的索引。
那麼我們在a,b上建聯合索引,彷彿有些問題。理論上不會在這樣的一個沒有多大區分度的a值上建索引的,所以一般看到INDEX SKIP SCAN,其一般開銷都很大。

三 示例

user_info表:

在這裏插入圖片描述
索引信息:
在這裏插入圖片描述

users表:

在這裏插入圖片描述
索引信息:
在這裏插入圖片描述

索引掃描:
1,單表

當查詢結果存在於對應的組合索引字段中時(無論順序)
在這裏插入圖片描述
當查詢結果不存在於對應的組合索引字段中時
在這裏插入圖片描述
當查詢條件(where)存在對應的組合索引字段(最左前綴原則
在這裏插入圖片描述
在這裏插入圖片描述
組合索引
id_combin(userName,password,school)–>(userName), (userName,password),(userName,school),(userName,password,school)

在這裏插入圖片描述
在這裏插入圖片描述
其中 where 條件沒有對應的順序(where school = ‘12’ and userName = ‘1’)和(where userName = ‘1’ and school= ‘12’) 沒有影響

2,排序

對於排序,如果你建立的組合索引 id_combin(userName,password,school),使用如下sql:

explain select * from user_info order by userName

這種是不會走索引:
在這裏插入圖片描述
這個問題可以參考官方給的這個extra中:Using filesort 參考:https://blog.csdn.net/qq_14869093/article/details/85694897

解決的方法,你需要把對應的查詢列包含進去:(這裏是不存在左原則)
在這裏插入圖片描述

3,join
EXPLAIN select * from user_info a LEFT JOIN users b on  a.PASSWORD = b.PASSWORD and a. userName = b.userName where a.userName = '1'

在這裏插入圖片描述

-- 只走對應的a表索引
EXPLAIN select * from user_info a LEFT JOIN users b on  a.userName = b.userName where a.userName = '1'

b表的組合索引id(password,userName),根據最左原則,因此沒有走b表的組合索引,where條件中含有對應a表的組合索引左userName,因此走了a表的索引
在這裏插入圖片描述

-- order by 不走a索引的問題(需要對應的查詢列中含有對應的)
-- 走b索引 
EXPLAIN select * from user_info a LEFT JOIN users b on  a.userName = b.PASSWORD order by a.school

在這裏插入圖片描述

-- 走a索引
-- 走b索引 
EXPLAIN select a.school from user_info a LEFT JOIN users b on  a.userName = b.PASSWORD order by a.school desc

在這裏插入圖片描述

-- 不走a索引,因爲address並不在組合索引中
-- 走b索引 
EXPLAIN select a.school,a.address from user_info a LEFT JOIN users b on  a.userName = b.PASSWORD order by a.school desc

在這裏插入圖片描述

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