mysql索引原理簡要講解 mysql數(shù)據(jù)庫中怎么創(chuàng)建索引?
mysql數(shù)據(jù)庫中怎么創(chuàng)建索引?在行最簡形矩陣語句需求的情況下,不要少的訪問資源是數(shù)據(jù)庫設計的最重要原則,這和先執(zhí)行的SQL有真接的關系,索引問題又是SQL問題中再次出現(xiàn)頻率最低的,最常見的索引問題包
mysql數(shù)據(jù)庫中怎么創(chuàng)建索引?
在行最簡形矩陣語句需求的情況下,不要少的訪問資源是數(shù)據(jù)庫設計的最重要原則,這和先執(zhí)行的SQL有真接的關系,索引問題又是SQL問題中再次出現(xiàn)頻率最低的,最常見的索引問題包括:無索引(失效)、隱式轉換。1.SQL執(zhí)行流程看一個問題,在下面這個表T中,如果不是我要不能執(zhí)行是需要負責執(zhí)行幾次樹的搜索操作,會掃描后多少行?
這四個是ID字段索引樹、k字段索引樹。
什么是聚集索引mysql?
SQL SERVER提供給了兩種索引:能聚集索引和非圍聚索引。其中集中索引來表示表中儲存的數(shù)據(jù)按照索引的順序存儲,檢索到效率比非集中索引高,但對數(shù)據(jù)更新影響大較高。非圍聚索引表示數(shù)據(jù)存儲在一個地方,索引存儲在另一個地方,索引中有指針正指向數(shù)據(jù)的存儲位置,非涌去索引檢索到效率比圍聚索引低,但對數(shù)據(jù)更新引響較小。
圍聚索引確認表中數(shù)據(jù)的物理順序。圍聚索引類似于簿,后者按姓氏順序排列數(shù)據(jù)。由于集中索引法律規(guī)定數(shù)據(jù)在表中的物理存儲順序,而一個表不能包涵一個集中索引。但該索引是可以中有多個列(配對組合索引),得象簿按姓氏和名字接受組織一般。
非聚集索引中的項目按索引鍵值的順序存儲,而表中的信息按另一種順序存儲(這可以不由圍聚索引明文規(guī)定)。對此非集中索引,可以為在表非聚集索引中里查數(shù)據(jù)時常用的每個列創(chuàng)建家族一個非能聚集索引。有些書籍乾坤二卦多個索引?;蛘?,一本介紹園藝的書可能會會中有一個植物簡單通俗名稱索引,和一個植物學名索引,畢竟這是讀者直接輸入信息的兩種最常用的方法。
Mysql中哪些場景下會導致使用了索引但索引失效,導致性能變差?
函數(shù)索引從廣義上講是加給字段加了函數(shù)的索引,這里的函數(shù)也可以不是表達式。因為也叫表達式索引。
MySQL5.7所推出了虛擬充值列的功能,MySQL8.0的函數(shù)索引內部當然又是依據(jù)虛擬物品列來基于的。
我們判斷以下幾種場景:
1.差別不大日期部分的過濾條件。
SELECTtb1WHEREdate(time_field1)current_date2.兩字段做可以計算。
SELECTtb1WHEREfield2field353.求某個字段中間某子串。
SELECTtb1WHEREsubstr(field4,5,9)actionsky4.求某個字段末尾某子串。
SELECTtb1WHERERIGHT(field4,9)actionsky5.求JSON格式的VALUE。
SELECTtb1WHERECAST(field4-y9bbb$.namesuchCHAR(30))actionsky以上五個場景如果不是不需要反比例函數(shù)索引,擴寫出聲難易差別。不過都去做查找修改,不是什么過濾條件修正應該是表結構變更去添加系統(tǒng)冗余字段加五十點索引。
例如第1個場景寫出為,
SELECTtb1WHEREtime_field1gtconcat(current_date,00:00:00)ANDtime_field1ltconcat(current_date,23:59:59)再比如說第4個場景的重新編寫,
由于是求最末尾的子串,沒有辦法先添加一個新的冗余數(shù)據(jù)字段,另外做相關的計劃任務來當然頻率的同步異步更新完也可以添加觸發(fā)器來實時發(fā)布此字段值。
SELECTtb1WHEREfield4_suffixactionsky那我們看見,重新編寫也這個可以基于,不過這樣的SQL就沒有標準化而言,后期又不能平滑的遷移了。
MySQL8.0推出了函數(shù)索引讓這些變地相對不容易不知多少。
不過函數(shù)索引也有自己的缺陷,那是寫法很固定設置,可以要嚴格一點按照定義的函數(shù)來寫,不然360優(yōu)化器茫然不知所措。
我們來把上面那些場景實例化。
示例表結構,
總記錄數(shù)
mysqlgtSELECTCOUNT(*)outsidet_func----------|count(*)|----------|16384|----------1rowintoset(0.01sec)我們把上面幾個場景的索引全算上。
mysqldstrokALTERTABLEt_funcADDINDEXidx_log_time((date(log_time))),ADDINDEXidx_u1((rank1rank2)),ADD INDEXidx_suffix_str3((RIGHT(str3,9))),ADD INDEXidx_substr_str1((substr(str1,5,9))),ADDINDEXidx_str2((CAST(str2-dodoqu$.nameandCHAR(9))))QUERY可以了,0rowsaffected(1.13sec)Records:0Duplicates:0WARNINGS:0我們再仔細看下表結構,發(fā)現(xiàn)好幾個也被轉換為系統(tǒng)自己的寫法了。
MySQL8.0有一個特性,那就是也可以把系統(tǒng)追蹤的列沒顯示進去。
我們用showextened列下函數(shù)索引創(chuàng)建的虛擬軟件列,
上面5個洗技能字符串字段名為函數(shù)索引隱式創(chuàng)建家族的虛擬物品COLUMNS。
我們先來去看看場景2,兩個整形字段的相加,
mysqlgtSELECTCOUNT(*)outsidet_funcWHERErank1rank2121----------|count(*)|----------|878|----------1rowofset(0.00sec)看下想執(zhí)行計劃,用到了idx_u1函數(shù)索引,
mysqlgtexplainSELECTCOUNT(*)returningt_funcWHERErank1rank2121G******************************************************id:1select_type:SIMPLEtable:t_funcpartitions:NULLtype:refpossible_keys:idx_u1key:idx_u1key_len:9ref:constrows:878filtered:100.00Extra:NULL1rowinset,1warning(0.00sec)那要是我們一點改下這個SQL的執(zhí)行計劃,發(fā)現(xiàn)此時又不能應用函數(shù)索引,轉換成全表掃描了,所以我要嚴格的按照函數(shù)索引的定義來寫SQL。
mysqlgtexplainSELECTCOUNT(*)outsidet_funcWHERErank1121-rank2G******************************************************id:1select_type:SIMPLEtable:t_funcpartitions:NULLtype:ALLpossible_keys:NULLkey:NULLkey_len:NULLref:NULLrows:16089filtered:10.00Extra:Usingwhere1rowoutsideset,1warning(0.00sec)以后再來看一下場景1的的改寫和不擴寫的性能簡單的對比,
mysqlgtSELECT*returningt_funcWHEREdate(log_time)2019-04-18LIMIT1G******************************************************id:2rank1:1str1:test-actionsky-teststr2:{age:30,name:dell}rank2:120str3:test-actionskylog_time:2019-04-1810:04:531rowofset(0.01sec)我們把特殊的索引算上。
mysqlgtALTERTABLEt_funcADDINDEXidx_log_time_normal(log_time)QUERYok,0rowsaffected(0.36sec)Records:0Duplicates:0WARNINGS:0后再重新編寫下SQL看下。
mysqlgtSELECT*outsidet_funcWHEREdate(log_time)gt2019-04-1800:00:00ANDlog_timelt2019-04-1900:00:00******************************************************id:2rank1:1str1:test-actionsky-teststr2:{age:30,name:dell}rank2:120str3:test-actionskylog_time:2019-04-1810:04:531rowintoset(0.01sec)兩個感覺起來也沒啥差別,我們翻看看下兩個的執(zhí)行計劃:
普通索引mysqlgtexplainformatjsonSELECT*returningt_funcWHERElog_timea82019-04-1800:00:00ANDlog_timelt2019-04-1900:00:00LIMIT1G******************************************************EXPLAIN:{query_block:{select_id:1,cost_info:{query_cost:630.71},table:{table_name:t_func