国产成人精品18p,天天干成人网,无码专区狠狠躁天天躁,美女脱精光隐私扒开免费观看

后端接口如何提高性能?從 MySQL、ES、HBASE 等技術(shù)

發(fā)布時(shí)間:2022-05-26 12:48 來(lái)源:老劉博客 閱讀:70 作者:網(wǎng)絡(luò ) 欄目: 經(jīng)驗分享 歡迎投稿:712375056

本文目錄 顯示

1. MySQL查詢(xún)慢是什么體驗?

謝邀,利益相關(guān)。大多數互聯(lián)網(wǎng)應用場(chǎng)景都是讀多寫(xiě)少,業(yè)務(wù)邏輯更多分布在寫(xiě)上。對讀的要求大概就是要快。那么都有什么原因會(huì )導致我們完成一次出色的慢查詢(xún)呢?

1.1 索引

數據量不是很大時(shí),大多慢查詢(xún)可以用索引解決,大多慢查詢(xún)也因為索引不合理而產(chǎn)生。

MySQL 索引基于 B 樹(shù),這句話(huà)相信面試都背爛了,接著(zhù)就可以問(wèn)最左前綴索引、 B 樹(shù)和各種樹(shù)了。

說(shuō)到最左前綴,實(shí)際就是組合索引的使用規則,使用合理組合索引可以有效的提高查詢(xún)速度,為什么呢?

因為索引下推。如果查詢(xún)條件包含在了組合索引中,比如存在組合索引(a,b),查詢(xún)到滿(mǎn)足 a 的記錄后會(huì )直接在索引內部判斷 b 是否滿(mǎn)足,減少回表次數。同時(shí),如果查詢(xún)的列恰好包含在組合索引中,即為覆蓋索引,無(wú)需回表。索引規則估計都知道,實(shí)際開(kāi)發(fā)中也會(huì )創(chuàng )建和使用。問(wèn)題可能更多的是:為什么建了索引還慢?

1.1.1 什么原因導致索引失效

建了索引還慢,多半是索引失效(未使用),可用 explain 分析。索引失效常見(jiàn)原因有 :

  1. where 中使用 != 或 <> 或 or 或表達式或函數(左側)
  2. like 語(yǔ)句 % 開(kāi)頭
  3. 字符串未加’’
  4. 索引字段區分度過(guò)低,如性別
  5. 未匹配最左前綴

1.1.2 這些原因為什么導致索引失效

如果要 MySQL 給一個(gè)理由,還是那棵 B 樹(shù)。

函數操作

當在 查詢(xún) where = 左側使用表達式或函數時(shí),如字段 A 為字符串型且有索引, 有 where length(a) = 6查詢(xún),這時(shí)傳遞一個(gè) 6 到 A 的索引樹(shù),不難想象在樹(shù)的第一層就迷路了。

隱式轉換

隱式類(lèi)型轉換和隱式字符編碼轉換也會(huì )導致這個(gè)問(wèn)題。

  • 隱式類(lèi)型轉換對于 JOOQ 這種框架來(lái)說(shuō)一般倒不會(huì )出現。
  • 隱式字符編碼轉換在連表查詢(xún)時(shí)倒可能出現,即連表字段的類(lèi)型相同但字符編碼不同。
破壞了有序性

至于 Like 語(yǔ)句 % 開(kāi)頭、字符串未加 ’’ 原因基本一致,MySQL 認為對索引字段的操作可能會(huì )破壞索引有序性就機智的優(yōu)化掉了。

不過(guò),對于如性別這種區分度過(guò)低的字段,索引失效就不是因為這個(gè)原因。

1.1.3 性別字段為什么不要加索引

為什么索引區分度低的字段不要加索引。盲猜效率低,效率的確低,有時(shí)甚至會(huì )等于沒(méi)加。

對于非聚簇索引,是要回表的。假如有 100 條數據,在 sex 字段建立索引,掃描到 51 個(gè) male,需要再回表掃描 51 行。還不如直接來(lái)一次全表掃描呢。

所以,InnoDB 引擎對于這種場(chǎng)景就會(huì )放棄使用索引,至于區分度多低多少會(huì )放棄,大致是某類(lèi)型的數據占到總的 30% 左右時(shí),就會(huì )放棄使用該字段的索引,有興趣可以試一下。

1.1.4 有什么好用且簡(jiǎn)單的索引方法

前面說(shuō)到大多慢查詢(xún)都源于索引,怎么建立并用好索引。這里有一些簡(jiǎn)單的規則。

  • 索引下推:性別字段不適合建索引,但確實(shí)存在查詢(xún)場(chǎng)景怎么辦?如果是多條件查詢(xún),可以建立聯(lián)合索引利用該特性?xún)?yōu)化。
  • 覆蓋索引:也是聯(lián)合索引,查詢(xún)需要的信息在索引里已經(jīng)包含了,就不會(huì )再回表了。
  • 前綴索引:對于字符串,可以只在前 N 位添加索引,避免不必要的開(kāi)支。假如的確需要如關(guān)鍵字查詢(xún),那交給更合適的如 ES 或許更好。
  • 不要對索引字段做函數操作
  • 對于確定的、寫(xiě)多讀少的表或者頻繁更新的字段都應該考慮索引的維護成本。

1.1.5 如何評價(jià) MySQL 選錯了索引

有時(shí),建立了猛一看挺正確的索引,但事情卻沒(méi)按計劃發(fā)展。就像“為啥 XXX 有索引,根據它查詢(xún)還是慢查詢(xún)”。

此刻沒(méi)準要自信點(diǎn):我的代碼不可能有 BUG,肯定是 MySQL 出了問(wèn)題。MySQL 的確可能有點(diǎn)問(wèn)題。

這種情況常見(jiàn)于建了一大堆索引,查詢(xún)條件一大堆。沒(méi)使用你想讓它用的那一個(gè),而是選了個(gè)區分度低的,導致過(guò)多的掃描。造成的原因基本有兩個(gè):

  • 信息統計不準確:可以使用 analyze table x重新分析。
  • 優(yōu)化器誤判:可以 force index強制指定?;蛐薷恼Z(yǔ)句引導優(yōu)化器,增加或刪除索引繞過(guò)。

但根據我淺薄的經(jīng)驗來(lái)看,更可能是因為你建了些沒(méi)必要的索引導致的。不會(huì )真有人以為 MySQL 沒(méi)自己機靈吧?

除了上面這些索引原因外,還有下面這些不常見(jiàn)或者說(shuō)不好判斷的原因存在。

1.2 等MDL鎖

在 MySQL 5.5 版本中引入了 MDL,對一個(gè)表做 CRUD 操作時(shí),自動(dòng)加 MDL 讀鎖;對表結構做變更時(shí),加 MDL 寫(xiě)鎖。讀寫(xiě)鎖、寫(xiě)鎖間互斥。

當某語(yǔ)句拿 MDL 寫(xiě)鎖就會(huì )阻塞 MDL 讀鎖,可以使用show processlist命令查看處于Waiting for table metadata lock狀態(tài)的語(yǔ)句。

1.3 等f(wàn)lush

flush 很快,大多是因為 flush 命令被別的語(yǔ)句堵住,它又堵住了 select 。通過(guò)show processlist命令查看時(shí)會(huì )發(fā)現處于Waiting for table flush狀態(tài)。

1.4 等行鎖

某事物持有寫(xiě)鎖未提交。

1.5 當前讀

InnoDB 默認級別是可重復讀。設想一個(gè)場(chǎng)景:事物 A 開(kāi)始事務(wù),事務(wù) B 也開(kāi)始執行大量更新。B 率先提交, A 是當前讀,就要依次執行 undo log ,直到找到事務(wù) B 開(kāi)始前的值。

1.6 大表場(chǎng)景

在未二次開(kāi)發(fā)的 MYSQL 中,上億的表肯定算大表,這種情況即使在索引、查詢(xún)層面做到了較好實(shí)現,面對頻繁聚合操作也可能會(huì )出現 IO 或 CPU 瓶頸,即使是單純查詢(xún),效率也會(huì )下降。

且 Innodb 每個(gè) B 樹(shù)節點(diǎn)存儲容量是 16 KB,理論上可存儲 2kw 行左右,這時(shí)樹(shù)高為3層。我們知道,innodb_buffer_pool 用來(lái)緩存表及索引,如果索引數據較大,緩存命中率就堪憂(yōu),同時(shí) innodb_buffer_pool 采用 LRU 算法進(jìn)行頁(yè)面淘汰,如果數據量過(guò)大,對老或非熱點(diǎn)數據的查詢(xún)可能就會(huì )把熱點(diǎn)數據給擠出去。

所以對于大表常見(jiàn)優(yōu)化即是分庫分表和讀寫(xiě)分離了。

1.6.1 分庫分表

方案

是分庫還是分表呢?這要具體分析。

  • 如果磁盤(pán)或網(wǎng)絡(luò )有 IO 瓶頸,那就要分庫和垂直分表。
  • 如果是 CPU 瓶頸,即查詢(xún)效率偏低,水平分表。

水平即切分數據,分散原有數據到更多的庫表中。

垂直即按照業(yè)務(wù)對庫,按字段對表切分。

工具方面有 sharding-sphere、TDDL、Mycat。動(dòng)起手來(lái)需要先評估分庫、表數,制定分片規則選 key,再開(kāi)發(fā)和數據遷移,還要考慮擴容問(wèn)題。

問(wèn)題

實(shí)際運行中,寫(xiě)問(wèn)題不大,主要問(wèn)題在于唯一 ID 生成、非 partition key 查詢(xún)、擴容。

  • 唯一 ID 方法很多,DB 自增、Snowflake、號段、一大波GUID算法等。
  • 非 partition key 查詢(xún)常用映射法解決,映射表用到覆蓋索引的話(huà)還是很快的?;蛘呖梢院推渌?DB 組合。
  • 擴容要根據分片時(shí)的策略確定,范圍分片的話(huà)就很簡(jiǎn)單,而隨機取模分片就要遷移數據了。也可以用范圍 取模的模式分片,先取模再范圍,可以避免一定程度的數據遷移。

當然,如果分庫還會(huì )面臨事務(wù)一致性和跨庫 join 等問(wèn)題。

1.6.2 讀寫(xiě)分離

為什么要讀寫(xiě)分離

分表針對大表解決 CPU 瓶頸,分庫解決 IO 瓶頸,二者將存儲壓力解決了。但查詢(xún)還不一定。

如果落到 DB 的 QPS 還是很高,且讀遠大于寫(xiě) ,就可以考慮讀寫(xiě)分離,基于主從模式將讀的壓力分攤,避免單機負載過(guò)高,同時(shí)也保證了高可用,實(shí)現了負載均衡。

問(wèn)題

主要問(wèn)題有過(guò)期讀和分配機制。

  • 過(guò)期讀,也就是主從延時(shí)問(wèn)題,這個(gè)對于。
  • 分配機制,是走主還是從庫??梢灾苯哟a中根據語(yǔ)句類(lèi)型切換或者使用中間件。

1.7 小結

以上列舉了 MySQL 常見(jiàn)慢查詢(xún)原因和處理方法,介紹了應對較大數據場(chǎng)景的常用方法。

分庫分表和讀寫(xiě)分離是針對大數據或并發(fā)場(chǎng)景的,同時(shí)也為了提高系統的穩定和拓展性。但也不是所有的問(wèn)題都最適合這么解決。

2. 如何評價(jià) ElasticSearch

前文有提到對于關(guān)鍵字查詢(xún)可以使用 ES。那接著(zhù)聊聊 ES 。

2.1 可以干什么

ES 是基于 Lucene 的近實(shí)時(shí)分布式搜索引擎。使用場(chǎng)景有全文搜索、NoSQL Json 文檔數據庫、監控日志、數據采集分析等。

對非數據開(kāi)發(fā)來(lái)說(shuō),常用的應該就是全文檢索和日志了。ES 的使用中,常和 Logstash, Kibana 結合,也成為 ELK 。先來(lái)瞧瞧日志怎么用的。

下面是我司日志系統某檢索操作:打開(kāi) Kibana 在 Discover 頁(yè)面輸入格式如 “xxx” 查詢(xún)。

該操作可以在 Dev Tools 的控制臺替換為:

 GET yourIndex/_search{   "from" : 0, "size" : 10, "query" : {        "match_phrase" : {            "log" : "xxx"             }    }}

什么意思?Discover 中加上 “” 和 console 中的 match_phrase 都代表這是一個(gè)短語(yǔ)匹配,意味著(zhù)只保留那些包含全部搜索詞項,且位置與搜索詞項相同的文檔。

2.2 ES 的結構

在 ES 7.0 之前存儲結構是 Index -> Type -> Document,按 MySQL 對比就是 database – table – id(實(shí)際這種對比不那么合理)。7.0 之后 Type 被廢棄了,就暫把 index 當做 table 吧。

在 Dev Tools 的 Console 可以通過(guò)以下命令查看一些基本信息。也可以替換為 crul 命令。

1. GET /_cat/health?v&pretty:查看集群健康狀態(tài)2. GET /_cat/shards?v :查看分片狀態(tài)3. GET yourindex/_mapping   :index mapping結構4. GET yourindex/_settings   :index setting結構5. GET /_cat/indices?v   :查看當前節點(diǎn)所有索引信息

重點(diǎn)是 mapping 和 setting ,mapping 可以理解為 MySQL 中表的結構定義,setting 負責控制如分片數量、副本數量。

以下是截取了某日志 index 下的部分 mapping 結構,ES 對字符串類(lèi)型會(huì )默認定義成 text ,同時(shí)為它定義一個(gè)叫做 keyword 的子字段。這兩的區別是:text 類(lèi)型會(huì )進(jìn)行分詞, keyword 類(lèi)型不會(huì )進(jìn)行分詞。

"******": {    "mappings": {      "doc": {        "properties": {          "appname": {            "type": "text",            "fields": {              "keyword": {                "type": "keyword",                "ignore_above": 256              }            }

2.3 ES查詢(xún)?yōu)槭裁纯欤?/span>

分詞是什么意思?看完 ES 的索引原理你就 get 了。

ES 基于倒排索引。嘛意思?傳統索引一般是以文檔 ID 作索引,以?xún)热葑鳛橛涗?。倒排索引相反,根據已有屬性值,去找到相應的行所在的位置,也就是將單詞或內容作為索引,將文檔 ID 作為記錄。

下圖是 ES 倒排索引的示意圖,由 Term index,Team Dictionary 和 Posting List 組成。

ES 查詢(xún)?yōu)槭裁纯欤?

圖中的 Ada、Sara 被稱(chēng)作 term,其實(shí)就是分詞后的詞了。如果把圖中的 Term Index 去掉,是不是有點(diǎn)像 MySQL 了?Term Dictionary 就像二級索引,但 MySQL 是保存在磁盤(pán)上的,檢索一個(gè) term 需要若干次的 random access 磁盤(pán)操作。

而 ES 在 Term Dictionary 基礎上多了層 Term Index ,它以 FST 形式保存在內存中,保存著(zhù) term 的前綴,借此可以快速的定位到 Term dictionary 的本 term 的 offset 。而且 FST 形式和 Term dictionary 的 block 存儲方式都很節省內存和磁盤(pán)空間。

到這就知道為啥快了,就是因為有了內存中的 Term Index , 它為 term 的索引 Term Dictionary 又做了一層索引。

不過(guò),也不是說(shuō) ES 什么查詢(xún)都比 MySQL 快。檢索大致分為兩類(lèi)。

2.3.1 分詞后檢索

ES 的索引存儲的就是分詞排序后的結果。比如圖中的 Ada,在 MySQL 中

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng )、來(lái)自本網(wǎng)站內容采集于網(wǎng)絡(luò )互聯(lián)網(wǎng)轉載等其它媒體和分享為主,內容觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如侵犯了原作者的版權,請告知一經(jīng)查實(shí),將立刻刪除涉嫌侵權內容,聯(lián)系我們QQ:712375056,同時(shí)歡迎投稿傳遞力量。

国产午夜亚洲精品国产成人小说| 精品亚洲成在人线AV无码| 7777精品伊人久久久大香线蕉| A级毛片免费网站| 精品精品国产理论在线观看 | 狂躁美女大BBBBBB视频1|