數據庫索引之優化查詢速度


(一)索引的作用
索引通俗來講就相當於書的目錄,當我們根據條件查詢的時候,沒有索引,便需要全表掃描,數據量少還可以,一旦數據量超過百萬甚至千萬,一條查詢sql執行往往需要幾十秒甚至更多,5秒以上就已經讓人難以忍受了。

提升查詢速度的方向一是提升硬件(內存、cpu、硬盤),二是在軟件上優化(加索引、優化sql)。

(二)mysql的索引類型:
mysql的索引有5種:主鍵索引、普通索引、唯一索引、全文索引、聚合索引(多列索引)。

1)主鍵索引:主鍵索引是加在主鍵上的索引,設置主鍵(primary key)的時候,它是一種特殊的唯一索引,不允許有空值。一般是在建表的時候同時創建主鍵索引;

2)普通索引:創建在非主鍵列上的索引,這是最基本的索引;

3)唯一索引:索引列的值必須唯一,但允許有空值。

4)聚合索引:創建在多列上的索引。

(三)索引的語法:
查看某張表的索引:show index from 表名;

創建普通索引:alter table 表名 add index  索引名 (加索引的列) 

創建聚合索引:alter table 表名 add index  索引名 (加索引的列1,加索引的列2) 

刪除某張表的索引:drop index 索引名 on 表名;

(四)關於面試如何通過索引說數據庫優化能力
數據庫方面的技能要求,包括三個方面:

  第一,基本的增刪改查,存儲過程等技能,是否會用些group by,having,distinct,exist,in,with等高級點的語句,

  第二,有沒有設計表的經驗,

  第三也是關鍵一點,在數據庫優化方面,你是否有相關經驗。

  索引是數據庫優化所必需的工具,一般會問以下兩方面的問題:

①索引有什么代價?哪些場景下你需要建索引?或者有時候反過來問,哪些場景下不推薦建索引。

②建好索引之后,怎么才能最高效地利用索引?或者反過來問,請說出一個無法有效利用已建索引的案例。

  從結構上來看,索引好比是一棵B樹(也叫B*或者B+),假設學生表里只有學生ID和姓名兩列,該學生表里有1000個學生,學號分別從1到1000,如果針對ID建立索引,大致的結構如下圖所示。

 

如果我們要查找ID為111的學生,則數據庫系統就會走索引,根據根節點的指引,會找到第二層從左往右第二個數據塊,以此類推,會在第四層里得到ID為111的物理地址,然后直接從硬盤里找數據。反過來,如果沒有建索引,數據庫系統可能就要從一個大的范圍里逐一定位查找,效率就沒這么高了。

代價呢?

1索引需要占硬盤空間,這是空間方面的代價。
2一旦插入新的數據,就需要重新建索引,這是時間上的代價。
場景一,數據表規模不大(幾千行),即使不建索引,查詢語句的返回時間也不長,這時建索引的意義就不大。“性價比”不高。

場景二,某個商品表里有幾百萬條商品信息,同時每天會在一個時間點,往其中更新大概十萬條左右的商品信息,現在用where語句查詢特定商品時(比如wherename=‘XXX’)速度很慢。為了提升查詢效率可以建索引,但當每天更新數據時,又會重建索引,這是要耗費時間的。這時就需要綜合考慮,甚至可以在更新前刪除索引,更新后再重建。

場景三,從上圖中可以看到,因為在數據表里ID值都不相同,所以索引能發揮出比較大的作用。相反,如果某個字段重復率很高,如性別字段,或者某個字段大多數值是空(null),那么不建議對該字段建索引。

  請大家記住,一定是有業務需求了才會建索引。比如在一個商品表里,我們經常要根據name做查詢,如果沒有索引,查詢速度會很慢,這時就需要建索引。但在項目開發中,如果不經常根據商品編號查詢,那么就沒必要對編號建索引。

方法呢?

①語句一:select name from 商品表。不會用到索引,因為沒有where語句。

②語句二:select * from 商品表 wherename=‘Java書’,會用到索引,如果項目里經常用到name來查詢,且商品表的數據量很大,而name值的重復率又不高,那么建議建索引。

③語句三:select * from 商品表 where name like ‘Java%’這是個模糊查詢,會用到索引,用like進行模糊查詢時,如果第一個就是模糊的匹配符,比如where name like ‘%java’,那么在查詢時不會走索引。在其他情況下,只要%不出現在第一個位置,那么都能用到索引。

  學生成績表里有兩個字段:姓名和成績。現在對成績這個整數類型的字段建索引。

①第一種情況,當數字型字段遇到非等值操作符時,無法用到索引。

select name from 學生成績表 where 成績>95
,一旦出現大於符號,就不能用到索引,為了用到索引,我們應該改一下SQL語句里的where從句:

where 成績 in (96,97,98,99,100)
②第二種情況,如果對索引字段進行了某種左值操作,那么無法用到索引。

  能用到索引的寫法:

select name from 學生成績表 where 成績=60
  不能用到索引的寫法:

select name from 學生成績表 where 成績+40=100
③第三種情況,如果對索引字段進行了函數操作,那么無法用到索引。

  比如SQL語句:

select * from 商品表 where substr(name)=‘J’
我們希望查詢商品名首字母是J的記錄,可一旦針對name使用函數,即使name字段上有索引,也無法用到。

 

(五)數據庫優化問題
(1)根據服務層面:配置mysql性能優化參數;

(2)從系統層面增強mysql的性能:優化數據表結構、字段類型、字段索引、分表,分庫、讀寫分離等等。

(3)從數據庫層面增強性能:優化SQL語句,合理使用字段索引。

(4)從代碼層面增強性能:使用緩存和NoSQL數據庫方式存儲,如MongoDB/Memcached/Redis來緩解高並發下數據庫查詢的壓力。

(5)減少數據庫操作次數,盡量使用數據庫訪問驅動的批處理方法。

(6)不常使用的數據遷移備份,避免每次都在海量數據中去檢索。

(7)提升數據庫服務器硬件配置,或者搭建數據庫集群。

(8)編程手段防止SQL注入:使用JDBC PreparedStatement按位插入或查詢;正則表達式過濾(非法字符串過濾);
————————————————
版權聲明:本文為CSDN博主「aogogogo」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/zhouboke/article/details/80414787


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM