自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

MySQL性能優(yōu)化,索引和查詢優(yōu)化

數(shù)據(jù)庫 MySQL
要知道為什么使用索引,要知道如何去使用好索引,使自己的查詢達到最優(yōu)性能,需要先了解索引的數(shù)據(jù)結(jié)構(gòu)和磁盤的存取原理。

要知道為什么使用索引,要知道如何去使用好索引,使自己的查詢達到***性能,需要先了解索引的數(shù)據(jù)結(jié)構(gòu)和磁盤的存取原理。

參考博客:MySQL索引背后的數(shù)據(jù)結(jié)構(gòu)及算法原理

如上這篇博客寫的挺好,我就不再造輪子了,對如上博客,我總結(jié)如下幾個重要的要點:

1. 不使用順序查找,因為順序查找比較慢,通過特定數(shù)據(jù)結(jié)構(gòu)的特點來提升查詢速度,這種數(shù)據(jù)結(jié)構(gòu)就是可以理解成索引。

2. 索引一般以文件形式存儲在磁盤上,索引檢索需要磁盤I/O操作,為了盡量減少磁盤I/O。磁盤往往不是嚴格按需讀取,而是每次都會預(yù)讀,而且主存和磁盤以頁為單位交換數(shù)據(jù),所以在讀取的數(shù)據(jù)不在主存中時,會從磁盤中讀取一批數(shù)據(jù)(頁)到主存中。

 

3. 不管在哪種程序優(yōu)化上,要想快速挺高性能,直接將常用的、少變更的數(shù)據(jù)直接讀取到內(nèi)存中,使用的時候就直接在內(nèi)存上讀取,而不去磁盤上讀取,減少I/O操作,這樣就能使程序快上10倍以上。但由于內(nèi)存容量的限制,也不可能將所有的數(shù)據(jù)都放內(nèi)存中。

 

MySQL索引分類

普通索引:最基本的索引,沒有任何限制。

唯一索引:與”普通索引”類似,不同的就是:索引列的值必須唯一,但允許有空值。

主鍵索引:它是一種特殊的唯一索引,不允許有空值。

全文索引:僅可用于 MyISAM 表,針對較大的數(shù)據(jù),生成全文索引很耗時好空間。

組合索引:為了更多的提高mysql效率可建立組合索引,遵循”最左前綴“原則。

 

覆蓋索引(Covering Indexes)

就是直接走的索引,直接在內(nèi)存中就拿到值,不需要查詢數(shù)據(jù)庫。

如分頁就要走覆蓋索引,因為性能比較高。

 

聚簇索引(Clustered Indexes),主鍵就是聚集索引

聚簇索引保證關(guān)鍵字的值相近的元組存儲的物理位置也相同(所以字符串類型不宜建

立聚簇索引,特別是隨機字符串,會使得系統(tǒng)進行大量的移動操作),且一個表只能

有一個聚簇索引。因為由存儲引擎實現(xiàn)索引,所以,并不是所有的引擎都支持聚簇索

引。目前,只有solidDB和InnoDB支持。

 

非聚簇索引

二級索引葉子節(jié)點保存的不是指行的物理位置的指針,而是行的主鍵值。這意味著通

過二級索引查找行。

InnoDB對主鍵建立聚簇索引。如果你不指定主鍵,InnoDB會用一個具有唯一且非空值

的索引來代替。如果不存在這樣的索引,InnoDB會定義一個隱藏的主鍵,然后對其建

立聚簇索引。一般來說,DBMS都會以聚簇索引的形式來存儲實際的數(shù)據(jù),它是其它二

級索引的基礎(chǔ)。

 

優(yōu)化要注意的一些事(重點)

1. 索引其實就是一種歸類方式,當某一個字段屬性都不能歸類,建立索引后是沒什么效果的,或歸類就二種(0和1),且各自都數(shù)據(jù)對半分,建立索引后的效果也不怎么強。

2. 主鍵的索引是不一樣的,要區(qū)別理解。

3. 當時間存儲為時間戳保存的可以建立前綴索引。

4. 在什么是字段上建立索引,需要根據(jù)查詢條件而定,不要一上來就建立索引,浪費內(nèi)存還有可能用不到。

5. 大字段(blob)不要建立索引,查詢也不會走索引。

6. 常用建立索引的地方:

1)主鍵的聚集索引

2)外鍵索引

3)類別只有0和1就不要建索引了,沒有意義,對性能沒有提升,還影響寫入性能

4)用模糊其實是可以走前綴索引

7. 唯一索引一定要小心使用,它帶有唯一約束,由于前期需求不明等情況下,可能造成我們對于唯一列的誤判。

8. 由于我們建立索引并想讓索引能達到***性能,這個時候我們應(yīng)當充分考慮該列是否適合建立索引,可以根據(jù)列的區(qū)分度來判斷,區(qū)分度太低的情況下可以不考慮建立索引,區(qū)分度越高效率越高。

 

  1. SELECT COUNT(DISTINCT 列_xx)/COUNT(*) FROM 表 

9. 寫入比較頻繁的時候,不能開啟MySQL的查詢緩存,因為在每一次寫入的時候不光要寫入磁盤還的更新緩存中的數(shù)據(jù)。

10. 建索引的目的:

1)加快查詢速度,使用索引后查詢有跡可循。

2)減少I/O操作,通過索引的路徑來檢索數(shù)據(jù),不是在磁盤中隨機檢索。

3)消除磁盤排序,索引是排序的,走完索引就排序完成。

11. 其實建索引的原理就是將磁盤I/O操作的最小化,不在磁盤中排序,而是在內(nèi)存中排好序,通過排序的規(guī)則去指定磁盤讀取就行,也不需要在磁盤上隨機讀取。

12. 由于磁盤整理磁盤碎片,所有有的時候我們也可以通過建立聚集索引來減少這一類的問題。

13. 當一個表中有100萬數(shù)據(jù),而經(jīng)常用到的數(shù)據(jù)只有40萬或40萬以下,是不用考慮建立索引的,沒什么性能提升。

14. 什么時候不適合建立索引:

1)頻繁更新的字段不適合建立索引

2)where條件中用不到的字段不適合建立索引,都用不到建立索引沒有意義還浪費空間

3)表數(shù)據(jù)可以確定比較少的不需要建索引

4)數(shù)據(jù)重復(fù)且發(fā)布比較均勻的的字段不適合建索引(唯一性太差的字段不適合建立索引),例如性別,真假值

5)參與列計算的列不適合建索引,如:

select * from table where amount+100>1000,-- 這樣是不走索引的,可以改造為:select * from table where amount>1000-100。

15. 使用count統(tǒng)計數(shù)據(jù)量的時候建議使用count(*)而不是count(列),因為count(*)MySQL是做了優(yōu)化的。

16. 二次SQL查詢區(qū)別不大的時候,不能按照二次執(zhí)行的時間來判斷優(yōu)化結(jié)果,沒準***次查詢后又保存緩存數(shù)據(jù),導(dǎo)致第二次查詢速度比第二次快,很多時候我們看到的都是假象。

17. 什么時候開MySQL的查詢緩存,交易系統(tǒng)(寫多、讀少)、SQL優(yōu)化測試,建議關(guān)閉查詢緩存,論壇文章類系統(tǒng)(寫少、讀多),建議開啟查詢緩存。

18. Explain 執(zhí)行計劃只能解釋SELECT操作。

19. 查詢優(yōu)化可以考慮讓查詢走索引,走索引能提升查詢速度,索引覆蓋是最快的,如下就是讓分頁走覆蓋索引提高查詢速度。

 

  1. Select * from fentrust e 
  2.  
  3. Inner join (select fid from fentrust limit 4100000, 10) a on a.fid = e.fid 

 

20. 子查詢比join快,雖然規(guī)律不絕對,但對大表多數(shù)有效

21. 復(fù)雜SQL語句優(yōu)化的思路:

1)首先考慮在一個表中能不能取到有關(guān)的信息,盡量少關(guān)聯(lián)表

2)關(guān)聯(lián)條件爭取都走主鍵或外鍵查詢條件,能走到對應(yīng)的索引

3)爭取在滿足業(yè)務(wù)上走小集合數(shù)據(jù)查找

4)INNER JOIN 和子查詢哪個更快,場景不一致速度也不同

22. where條件多條件一定要按照小結(jié)果集排大結(jié)果集前面

23. 盡量避免大事務(wù)操作,提高系統(tǒng)并發(fā)能力,有時無法避免,改用定時器延遲處理。

24. 什么情況不走索引:

 

  1. SELECT ` famount ` FROM ` fentrust ` WHERE ` famount `+10=30;-- 不會使用索引,因為所有索引列參與了計算   
  2. SELECT `famount` FROM `fentrust` WHERE LEFT(`fcreateTime`,4) <1990; -- 不會使用索引,因為使用了函數(shù)運算,原理與上面相同   
  3. SELECT * FROM ` fuser` WHERE `floginname` LIKE‘138%' -- 走索引   
  4. SELECT * FROM ` fuser ` WHERE ` floginname ` LIKE "%7488%" -- 不走索引 -- 正則表達式不使用索引,這應(yīng)該很好理解,所以為什么在SQL中很難看到regexp關(guān)鍵字的原因 -- 字符串與數(shù)字比較不使用索引;   
  5. EXPLAIN SELECT * FROM `a` WHERE `a`=1 -- 不走索引   
  6. select * from fuser where floginname='xxx' or femail='xx' or fstatus=1 --如果條件中有or,即使其中有條件帶索引也不會使用。換言之,就是要求使用的所有字段,都必須建立索引, 我們建議大家盡量避免使用or 關(guān)鍵字  

 

25. 如果MySQL估計使用全表掃描要比使用索引快,則不使用索引。

26. 使用UNION ALL 替換OR多條件查詢并集。

27. 在大數(shù)據(jù)表刪除也是一個問題,避免刪除過程數(shù)據(jù)庫奔潰,可以考慮分配刪除,一次刪1000條,刪完后等一會繼續(xù)刪除

 

  1. delete from logs where log_date <= ’2012-11-01’ limit 1000 

28. 大數(shù)據(jù)表優(yōu)化:

1)建立匯總表

2)建立流水表

3)分庫分表

29. 建立匯總表,首先不用考慮分庫分表,使用定時器定時去匯總。

30. 分表,可以按水平或垂直切分。垂直分表其實就是將經(jīng)常使用的數(shù)據(jù)和很少使用的數(shù)據(jù)進行垂直的切分,切分到不同的庫,提高單庫的數(shù)據(jù)容量,如:前3個月之前的交易記錄就可以放另一個庫中。

31. 建立流水表,數(shù)據(jù)冗余,有這個表記錄流水變更就不用去寫復(fù)雜SQL計算流水。

32. 分庫,多數(shù)據(jù)庫相同庫結(jié)構(gòu),分發(fā)處理并發(fā)能力,但同時帶來了數(shù)據(jù)同步問題,也可以使用分庫做主備分離

32. SQL優(yōu)化順序:

1)盡量少作計算。

2)盡量少 join。

3)盡量少排序。

4)盡量避免 select *。

5)盡量用 join 代替子查詢。

6)盡量少 or。

7)盡量用 union all 代替 union。

8)盡量早過濾。

9)避免類型轉(zhuǎn)換。

10)優(yōu)先優(yōu)化高并發(fā)的 SQL,而不是執(zhí)行頻率低某些“大”SQL。

11)從全局出發(fā)優(yōu)化,而不是片面調(diào)整。

12)盡可能對每一條運行在數(shù)據(jù)庫中的SQL進行 Explain。

33. 如下是30條大數(shù)據(jù)表優(yōu)化要點:

1)對查詢進行優(yōu)化,應(yīng)盡量避免全表掃描,首先應(yīng)考慮在 where 及 order by 涉及的列上建立索引。

2)應(yīng)盡量避免在 where 子句中對字段進行 null 值判斷,否則將導(dǎo)致引擎放棄使用索引而進行全表掃描,如:select id from t where num is null可以在num上設(shè)置默認值0,確保表中num列沒有null值,然后這樣查詢:select id from t where num=0

3)應(yīng)盡量避免在 where 子句中使用!=或<>操作符,否則引擎將放棄使用索引而進行全表掃描。

4)應(yīng)盡量避免在 where 子句中使用or 來連接條件,否則將導(dǎo)致引擎放棄使用索引而進行全表掃描,如:select id from t where num=10 or num=20可以這樣查詢:select id from t where num=10 union all select id from t where num=20

5)in 和 not in 也要慎用,否則會導(dǎo)致全表掃描,如:select id from t where num in(1,2,3) 對于連續(xù)的數(shù)值,能用 between 就不要用 in 了:select id from t where num between 1 and 3

6)下面的查詢也將導(dǎo)致全表掃描:select id from t where name like '李%'若要提高效率,可以考慮全文檢索。

7)如果在 where 子句中使用參數(shù),也會導(dǎo)致全表掃描。因為SQL只有在運行時才會解析局部變量,但優(yōu)化程序不能將訪問計劃的選擇推遲到運行時;它必須在編譯時進行選擇。然 而,如果在編譯時建立訪問計劃,變量的值還是未知的,因而無法作為索引選擇的輸入項。如下面語句將進行全表掃描:select id from t where num=@num可以改為強制查詢使用索引:select id from t with(index(索引名)) where num=@num

8)應(yīng)盡量避免在 where 子句中對字段進行表達式操作,這將導(dǎo)致引擎放棄使用索引而進行全表掃描。如:select id from t where num/2=100應(yīng)改為:select id from t where num=100*2

9)應(yīng)盡量避免在where子句中對字段進行函數(shù)操作,這將導(dǎo)致引擎放棄使用索引而進行全表掃描。如:select id from t where substring(name,1,3)='abc' ,name以abc開頭的id 應(yīng)改為: select id from t where name like 'abc%'

10)不要在 where 子句中的“=”左邊進行函數(shù)、算術(shù)運算或其他表達式運算,否則系統(tǒng)將可能無法正確使用索引。

11)在使用索引字段作為條件時,如果該索引是復(fù)合索引,那么必須使用到該索引中的***個字段作為條件時才能保證系統(tǒng)使用該索引,否則該索引將不會被使用,并且應(yīng)盡可能的讓字段順序與索引順序相一致。

12)不要寫一些沒有意義的查詢,如需要生成一個空表結(jié)構(gòu):select col1,col2 into #t from t where 1=0 這類代碼不會返回任何結(jié)果集,但是會消耗系統(tǒng)資源的,應(yīng)改成這樣: create table #t(...)

13)很多時候用 exists 代替 in 是一個好的選擇:select num from a where num in(select num from b) 用下面的語句替換: select num from a where exists(select 1 from b where num=a.num)

14)并不是所有索引對查詢都有效,SQL是根據(jù)表中數(shù)據(jù)來進行查詢優(yōu)化的,當索引列有大量數(shù)據(jù)重復(fù)時,SQL查詢可能不會去利用索引,如一表中有字段sex,male、female幾乎各一半,那么即使在sex上建了索引也對查詢效率起不了作用。

15)索引并不是越多越好,索引固然可 以提高相應(yīng)的 select 的效率,但同時也降低了 insert 及 update 的效率,因為 insert 或 update 時有可能會重建索引,所以怎樣建索引需要慎重考慮,視具體情況而定。一個表的索引數(shù)***不要超過6個,若太多則應(yīng)考慮一些不常使用到的列上建的索引是否有 必要。

16)應(yīng)盡可能的避免更新 clustered 索引數(shù)據(jù)列,因為 clustered 索引數(shù)據(jù)列的順序就是表記錄的物理存儲順序,一旦該列值改變將導(dǎo)致整個表記錄的順序的調(diào)整,會耗費相當大的資源。若應(yīng)用系統(tǒng)需要頻繁更新 clustered 索引數(shù)據(jù)列,那么需要考慮是否應(yīng)將該索引建為 clustered 索引。

17)盡量使用數(shù)字型字段,若只含數(shù)值信息的字段盡量不要設(shè)計為字符型,這會降低查詢和連接的性能,并會增加存儲開銷。這是因為引擎在處理查詢和連接時會逐個比較字符串中每一個字符,而對于數(shù)字型而言只需要比較一次就夠了。

18)盡可能的使用 varchar/nvarchar 代替 char/nchar ,因為首先變長字段存儲空間小,可以節(jié)省存儲空間,其次對于查詢來說,在一個相對較小的字段內(nèi)搜索效率顯然要高些。

19)任何地方都不要使用 select * from t ,用具體的字段列表代替“*”,不要返回用不到的任何字段。

20)盡量使用表變量來代替臨時表。如果表變量包含大量數(shù)據(jù),請注意索引非常有限(只有主鍵索引)。

21)避免頻繁創(chuàng)建和刪除臨時表,以減少系統(tǒng)表資源的消耗。

22)臨時表并不是不可使用,適當?shù)厥褂盟鼈兛梢允鼓承├谈行В?,當需要重?fù)引用大型表或常用表中的某個數(shù)據(jù)集時。但是,對于一次性事件,***使用導(dǎo)出表。

23)在新建臨時表時,如果一次性插入數(shù)據(jù)量很大,那么可以使用 select into 代替 create table,避免造成大量 log ,以提高速度;如果數(shù)據(jù)量不大,為了緩和系統(tǒng)表的資源,應(yīng)先create table,然后insert。

24)如果使用到了臨時表,在存儲過程的***務(wù)必將所有的臨時表顯式刪除,先 truncate table ,然后 drop table ,這樣可以避免系統(tǒng)表的較長時間鎖定。

25)盡量避免使用游標,因為游標的效率較差,如果游標操作的數(shù)據(jù)超過1萬行,那么就應(yīng)該考慮改寫。

26)使用基于游標的方法或臨時表方法之前,應(yīng)先尋找基于集的解決方案來解決問題,基于集的方法通常更有效。

27)與臨時表一樣,游標并不是不可使 用。對小型數(shù)據(jù)集使用 FAST_FORWARD 游標通常要優(yōu)于其他逐行處理方法,尤其是在必須引用幾個表才能獲得所需的數(shù)據(jù)時。在結(jié)果集中包括“合計”的例程通常要比使用游標執(zhí)行的速度快。如果開發(fā)時 間允許,基于游標的方法和基于集的方法都可以嘗試一下,看哪一種方法的效果更好。

28)在所有的存儲過程和觸發(fā)器的開始處設(shè)置 SET NOCOUNT ON ,在結(jié)束時設(shè)置 SET NOCOUNT OFF 。無需在執(zhí)行存儲過程和觸發(fā)器的每個語句后向客戶端發(fā)送DONE_IN_PROC 消息。

29)盡量避免大事務(wù)操作,提高系統(tǒng)并發(fā)能力。

30)盡量避免向客戶端返回大數(shù)據(jù)量,若數(shù)據(jù)量過大,應(yīng)該考慮相應(yīng)需求是否合理。

責任編輯:龐桂玉 來源: 秋日芒草的博客
相關(guān)推薦

2024-09-19 08:09:37

MySQL索引數(shù)據(jù)庫

2020-10-19 19:45:58

MySQL數(shù)據(jù)庫優(yōu)化

2024-10-09 23:32:50

2010-05-27 16:12:10

MySQL索引

2021-07-16 23:01:03

SQL索引性能

2010-06-03 09:24:46

Oracle

2024-04-03 09:12:03

PostgreSQL索引數(shù)據(jù)庫

2023-12-14 12:56:00

MongoDB數(shù)據(jù)庫優(yōu)化

2020-12-02 08:30:46

MySQL索引哈希表

2010-06-12 15:31:04

MySQL查詢優(yōu)化

2021-07-26 18:23:23

SQL策略優(yōu)化

2018-07-11 20:07:06

數(shù)據(jù)庫MySQL索引優(yōu)化

2011-08-15 18:09:46

查詢性能調(diào)優(yōu)索引優(yōu)化

2017-08-25 15:28:20

Oracle性能優(yōu)化虛擬索引

2010-03-02 09:53:14

MySQL性能優(yōu)化

2020-03-23 15:15:57

MySQL性能優(yōu)化數(shù)據(jù)庫

2009-04-20 08:51:50

MySQL查詢優(yōu)化數(shù)據(jù)庫

2023-07-12 08:55:16

PawSQL數(shù)據(jù)庫

2012-09-20 10:13:04

MongoDB

2024-04-17 12:58:15

MySQL索引數(shù)據(jù)庫
點贊
收藏

51CTO技術(shù)棧公眾號