SQL什麼條件會使用索引?
當字段上建有索引時,一般如下狀況會使用索引:
INDEX_COLUMN = 、> 、>= 、< 、<= 、?between ? and ?、in (?,?,...,?)、like ?||'%'(後導模糊查詢)
T1. INDEX_COLUMN=T2. COLUMN1(兩個表經過索引字段關聯)
SQL什麼條件不會使用索引?
<> not in (?,?,...,?)
function(INDEX_COLUMN) = ?
INDEX_COLUMN + 1 = ?
INDEX_COLUMN || 'a' = ?
通過普通運算或函數運算後的索引字段不能使用索引
INDEX_COLUMN like '%'||?
INDEX_COLUMN like '%'||?||'%'
含前導模糊查詢的Like語法不能使用索引
INDEX_COLUMN is null
B-TREE索引裏不保存字段爲NULL值記錄,所以IS NULL不能使用索引
NUMBER_INDEX_COLUMN='12345'
CHAR_INDEX_COLUMN=12345
Oracle在作數值比較時須要將兩邊的數據轉換成同一種數據類型,若是兩邊數據類型不一樣時會對字段值隱式轉換,至關於加了一層函數處理,因此不能使用索引。
a.INDEX_COLUMN=a.COLUMN_1
給索引查詢的值應是已知數據,不能是未知字段值。
注:通過函數運算字段的字段要使用可使用函數索引,這種需求建議與DBA溝通。
有時候咱們會使用多個字段的組合索引,若是查詢條件中第一個字段不能使用索引,那整個查詢也不能使用索引
咱們通常在什麼字段上建索引?
這是一個很是複雜的話題,須要對業務及數據充分分析後再能得出結果。主鍵及外鍵一般都要有索引,其它須要建索引的字段應知足如下條件:
一、字段出如今查詢條件中,而且查詢條件可使用索引;
二、語句執行頻率高,一天會有幾千次以上;
如下是一些字段是否須要建的經驗分類:
須要建索引的字段
主鍵、外鍵、有標識意義字段
數據庫
長字符不適合建索引的字段、描述備註、大字段
如何知道SQL是否使用了正確的索引?
簡單SQL能夠根據索引使用語法規則判斷,複雜的SQL很差辦,判斷SQL的響應時間是一種策略,可是這會受到數據量、主機負載及緩存等因素的影響,有時數據全在緩存裏,可能全表訪問的時間比索引訪問時間還少。要準確知道索引是否正確使用,須要到數據庫中查看SQL真實的執行計劃,這個話題比較複雜,詳見SQL執行計劃專題介紹。
索引對DML(INSERT,UPDATE,DELETE)附加的開銷有多少?這個沒有固定的比例,與每一個表記錄的大小及索引字段大小密切相關,如下是一個普通表測試數據,僅供參考:
索引對於Insert性能下降56%
索引對於Update性能下降47%
索引對於Delete性能下降29%
所以對於寫IO壓力比較大的系統,表的索引須要仔細評估必要性,另外索引也會佔用必定的存儲空間。瀏覽器
有些時候,咱們只是訪問表中的幾個字段,而且字段內容較少,咱們能夠爲這幾個字段單獨創建一個組合索引,這樣就能夠直接只經過訪問索引就能獲得數據,通常索引佔用的磁盤空間比表小不少,因此這種方式能夠大大減小磁盤IO開銷。如:select id,name from company where type='2';若是這個SQL常用,咱們能夠在type,id,name上建立組合索引create index my_comb_index on company(type,id,name);有了這個組合索引後,SQL就能夠直接經過my_comb_index索引返回數據,不須要訪問company表。
仍是拿字典舉例:有一個需求,須要查詢一本漢語字典中全部漢字的個數,若是咱們的字典沒有目錄索引,那咱們只能從字典內容裏一個一個字計數,最後返回結果。若是咱們有一個拼音目錄,那就能夠只訪問拼音目錄的漢字進行計數。若是一本字典有1000頁,拼音目錄有20頁,那咱們的數據訪問成本至關於全表訪問的50分之一。
切記,性能優化是無止境的,當性能能夠知足需求時便可,不要過分優化。在實際數據庫中咱們不可能把每一個SQL請求的字段都建在索引裏,因此這種只經過索引訪問數據的方法通常只用於核心應用,也就是那種對核心表訪問量最高且查詢字段數據量不多的查詢。緩存
將數據從應用服務器所有下載到本地應用程序或瀏覽器,在應用程序或瀏覽器內部經過本地代碼進行分頁處理
優勢:編碼簡單,減小客戶端與應用服務器網絡交互次數
缺點:首次交互時間長,佔用客戶端內存
適應場景:客戶端與應用服務器網絡延時較大,但要求後續操做流暢,如手機GPRS,超遠程訪問(跨國)等等。性能優化
將數據從數據庫服務器所有下載到應用服務器,在應用服務器內部再進行數據篩選。如下是一個應用服務器端Java程序分頁的示例:List list=executeQuery(「select * from employee order by id」);服務器
Int count= list.size();List subList= list.subList(10, 20);
優勢:編碼簡單,只須要一次SQL交互,總數據與分頁數據差很少時性能較好。
缺點:總數據量較多時性能較差。
適應場景:數據庫系統不支持分頁處理,數據量較小而且可控。網絡
採用數據庫SQL分頁須要兩次SQL完成
一個SQL計算總數量
一個SQL返回分頁後的數據
優勢:性能好
缺點:編碼複雜,各類數據庫語法不一樣,須要兩次SQL交互。框架
數據庫訪問框架通常都提供了批量提交的接口,jdbc支持batch的提交處理方法,當你一次性要往一個表中插入1000萬條數據時,若是採用普通的executeUpdate處理,那麼和服務器交互次數爲1000萬次,按每秒鐘能夠向數據庫服務器提交10000次估算,要完成全部工做須要1000秒。若是採用批量提交模式,1000條提交一次,那麼和服務器交互次數爲1萬次,交互次數大大減小。採用batch操做通常不會減小不少數據庫服務器的物理IO,可是會大大減小客戶端與服務端的交互次數,從而減小了屢次發起的網絡延時開銷,同時也會下降數據庫的CPU開銷。函數
對於一次查詢多個id的狀況儘可能用in,而不是循環屢次去數據庫查詢。能夠減小與數據庫交互。性能
當咱們採用select從數據庫查詢數據時,數據默認並非一條一條返回給客戶端的,也不是一次所有返回客戶端的,而是根據客戶端fetch_size參數處理,每次只返回fetch_size條記錄,當客戶端遊標遍歷到尾部時再從服務端取數據,直到最後所有傳送完成。因此若是咱們要從服務端一次取大量數據時,能夠加大fetch_size,這樣能夠減小結果數據傳輸的交互次數及服務器數據準備時間,提升性能。學習
存儲過程能夠提升性能,可是一樣存在缺點,不可移植性,學習成本高,業務邏輯多處存在不方便後期維護。 普通業務邏輯儘可能不要使用存儲過程,定時性的ETL任務或報表統計函數能夠根據團隊資源狀況採用存儲過程處理。
連表操做操做時儘可能數量少的表做爲主表,
綁定變量是指SQL中對變化的值採用變量參數的形式提交,而不是在SQL中直接拼寫對應的值。
非綁定變量寫法:Select * from employee where id=1234567
綁定變量寫法:
Select * from employee where id=? Preparestatement.setInt(1,1234567)
Java中Preparestatement就是爲處理綁定變量提供的對像,綁定變量有如下優勢:
一、防止SQL注入
二、提升SQL可讀性
三、提升SQL解析性能,不使用綁定變動咱們通常稱爲硬解析,使用綁定變量咱們稱爲軟解析。
儘可能少使用like ‘%abc%’