索引的底層理解
最近看了很多文章,這裏再補充一下對索引底層的理解,僅個人意見,有不對的,大家可以留言下,非常歡迎~
關於什麽是索引,索引的建立,索引不同存儲引擎可以在之前的文章了解到
請點擊這裏:http://www.cnblogs.com/houdashuai/p/6681680.html
這次總結一下,重點說一下底層結構
索引
一、索引的分類;
二、創建表時會影響到索引的因素;
三、使用SQL時會影響到索引的因素;
四、根據索引的優缺點去概述一下索引的底層結構
一、索引的分類;
普通索引「INDEX」: 增加索引結構,對數據列增加普通索引
全文索引「FULLTEXT」: 增加索引結構,全文索引適用於文章查詢,一般用普通索引就可以
唯一索引「UNIQUE」: 增加索引結構,數據不允許出現重復,但是可以為空,空就是空,不等於0,也不等於空字符串
主鍵索引「PRIMARY」: 增加索引結構,數據不允許出現重復,但是不可以為空
聯合索引: 根據左前綴原則合理創建,這裏不多介紹
二、創建表時會影響到索引的因素;
針對於數據庫查詢,數據庫字段肯定是越小,越少的元素會很快
那麽在創建表時,對字段的約束盡量以數據類型為主:
1. 盡量以INT數值去做索引列,因為數值的查詢效率總是大於文字
2. 數據列字段盡量範圍越小越好,這種區別在千萬級數據庫中或者單張表字段很多時會有很大差距,tinyint就是用tinyint,不要用int,或者char
3. 還有字段盡量給 NOT NULL,盡量給 NOT NULL,盡量給 NOT NULL,這個要註意下,因為索引對空值的判斷很復雜,可以給默認值填充空字符串。
三、使用SQL時會影響到索引的因素;
會影響到全表掃描的語句,像 NOT IN 、LIKE、<>、!=、or......這些explain 看一下語句級別和影響行數註意一下
說一下兩個常用的點:
1. limit:
limit 一般用到分頁,但是如果數據很多的話,一般都是這樣寫的 limit 100,200
如果場景允許的話可以適用一下這種方式:
WHERE uid>100 LIMIT 200
原因:limit會產生全表掃描,但是可以用WHERE篩選掉一部分數據,這樣會節省很多查詢時間,大家可以嘗試一下這種方式~
2. *:count(0)、count(*)
網上對星號的歧義有很多,這兩種哪個效率高,我覺得用*號應用性更好一些(部分場景),每個項目都會封裝model層,這些一般都是封裝單張表的SQL
SELECT COUNT(*) FROM `demo`;
SELECT * FROM `demo`;
如果查詢涉及到一張表建議還是用*號,考慮到擴展性、及效率
擴展性:網站業務擴展,字段增加,如果不用*號那就不可避免的要更改最底層的代碼,這種操作很危險;
效率:效率來講,*號會自動匹配到這張表中查詢效率最優的數據列,從而獲取到數據,如果是單張表我還是建議用*號,但是如果是關聯表就不建議使用*號了,關聯表那影響查詢效率就翻倍了。
四、根據索引的優缺點去概述一下索引的底層結構
優點:增加查詢速度
缺點:影響寫的效率
問題:為什麽會影響寫的效率
每創建一個索引,都會創建一條依據這個索引的索引查詢結構,也就是平衡樹結構;
可以這樣理解,每創建一條索引都會生成一個索引結構文件,這個文件存的不是數據,而是數據的【指針】,索引根據二分算法也就是B+Tree、B-Tree的算法去查詢到數據的指針,再拿到數據。
講到這裏就有一個問題,索引的產生肯定是維持在一個正確的平衡術狀態,那麽每一次做增、刪、改的操作時就會重新排序索引文件結構,那麽索引如果有一條,兩條,三條,的時候,那麽索引越多豈不是很影響寫的效率,因為每一條索引結構都會重新排序,並且當數據量過於巨大時,每一次寫操作,對於數據庫的壓力也會非常大;
所有的優化都是空間換時間,或者時間換空間;
這裏想強調一下:對於優化而言網上有提供很多種,但是這裏還是說一下級別,能在表,SQL,計算機硬件上做優化盡量先考慮這些,之後可以再考慮主從,讀寫分離,負載均衡,不到很卡頓盡量還是不要做分庫分表,因為目前而言大都是關系型數據庫居多,以關系為主,過多的做子表拆分也就擴大了關系型數據庫的弊端,也可以考慮一下NoSQL,當然如果涉及到表設計需要分表這個另說,像這種關系型數據庫,億級以下的數據用索引,SQL優化,架構優化,讀寫分離,主從完全可以搞得定,如果還是卡,那就硬件提升一下,4G上8G,速度絕對有提升很多,盡量從其他方面考慮,MySQL畢竟也是一種開發語言,吼住上億數據還是毛毛雨的~
索引的底層理解