日本黄色一级经典视频|伊人久久精品视频|亚洲黄色色周成人视频九九九|av免费网址黄色小短片|黄色Av无码亚洲成年人|亚洲1区2区3区无码|真人黄片免费观看|无码一级小说欧美日免费三级|日韩中文字幕91在线看|精品久久久无码中文字幕边打电话

當(dāng)前位置:首頁 > > 后端技術(shù)指南針
[導(dǎo)讀]熟悉 MySQL 的同學(xué)一定都知道,MySQL 對于復(fù)雜條件查詢的支持并不好。


熟悉 MySQL 的同學(xué)一定都知道,MySQL 對于復(fù)雜條件查詢的支持并不好。MySQL 最多使用一個條件涉及的索引來過濾,然后剩余的條件只能在遍歷行過程中進行內(nèi)存過濾,對這個過程不了解的同學(xué)可以先行閱讀一下《MySQL復(fù)雜where條件分析》。 上述這種處理復(fù)雜條件查詢的方式因為只能通過一個索引進行過濾,所以需要進行大量的 I/O 操作來讀取行數(shù)據(jù),并消耗 CPU 進行內(nèi)存過濾,導(dǎo)致查詢性能的下降。

而 ElasticSearch 因其特性,十分適合進行復(fù)雜條件查詢,是業(yè)界主流的復(fù)雜條件查詢場景解決方案,廣泛應(yīng)用于訂單和日志查詢等場景。

下面我們就一起來看一下,為什么 ElasticSearch 適合進行復(fù)雜條件查詢。

ElasticSearch 簡介

Elasticsearch 是開源的實時分布式搜索分析引擎,內(nèi)部使用 Lucene 做索引與搜索。它提供"準(zhǔn)實時搜索"能力,并且能動態(tài)集群規(guī)模,彈性擴容。

Elasticsearch 使用 Lucene 作為其全文搜索引擎,用于處理純文本的數(shù)據(jù),但 Lucene 只是一個庫,提供建立索引、執(zhí)行搜索等接口,但不包含分布式服務(wù),這些正是 Elasticsearch 做的。

下面,我們來介紹一下 ElasticSearch 的相關(guān)概念。為了便于初學(xué)者理解,我們先將 ElasticSearch 中的概念和 MySQL 中的概念大致地進行對應(yīng)。但是二者在具體細節(jié)上還是有很多差異的,大家深入了解 ElasticSearch 就會將二者區(qū)分清楚,不能強行對比等同。

  • ElasticSearch 中的索引 Index 類似于 MySQL 中的數(shù)據(jù)庫 Database;

  • ElasticSearch 中的類型 Type 類似于 MySQL 中的表 Table;需要注意,這個概念在 7.x 版本中被完全刪除,而且概念上和 Table 也有較大差異;

  • ElasticSearch 中的文檔 Document 類似于 MySQL 中的數(shù)據(jù)行 Row,每個文檔由多個字段 Filed 組成,這個Filed 就類似于 MySQL 的 Column;

  • ElasticSearch 中的映射 Mapping 是對索引庫中的索引字段及其數(shù)據(jù)類型進行定義,類似于關(guān)系型數(shù)據(jù)庫中的表結(jié)構(gòu) Schema;

  • ElasticSearch 使用自己的領(lǐng)域語言 Query DSL 來進行增刪改查,而 MySQL 使用 SQL 語言進行上訴操作。

ElasticSearch 還有一系列有關(guān)其分布式特性的概念,我們這里就暫不介紹了,等后續(xù)學(xué)習(xí)到其分布式特性時在進行介紹。

倒排索引

MySQL 有 B+ 樹索引,而 ElasticSearch 則是倒排索引 (Inverted Index),它通過倒排索引來實現(xiàn)比 MySQL 更快的過濾和復(fù)雜條件的查詢,此外,全文搜索功能也是依賴倒排索引才能實現(xiàn)。下面,我們就具體來看一下何為倒排索引。

倒排索引按照維基百科的描述,是存儲文檔內(nèi)容到文檔位置映射關(guān)系的數(shù)據(jù)庫索引結(jié)構(gòu)。不過只看定義,我是有點迷惑,這不是和 MySQL 的非主鍵索引類似嘛,為什么要叫它“倒排”呢?這個問題我目前也為搞清楚,可能要等到后續(xù)了解了其具體實現(xiàn)才能理解。

我們還是以書籍檢索為例,假設(shè)有以下數(shù)據(jù),每一行就是一個 Document,每個 Document 由 id,ISBN 號,作者名稱和評分組成。

給上述數(shù)據(jù)按照 ISBN 和 Author 建立的倒排索引如下所示。倒排索引是每個字段分開建立的,相互獨立。有兩個專門的術(shù)語,分別是索引 Term 和倒排表 Posting List。字段的值就是 Term,比如 N0007,而 Term 對應(yīng)的文檔 ID 的列表就是 Posting List,對應(yīng)圖中紅色的部分。

一般 Term 都是按照順序排序的,比如 Author 名稱就是按照字母序進行了排序,排序之后,當(dāng)我們搜索某一個 Term 時,就不需要從頭遍歷,而是采用二分查找。一系列排序后的 Term 就組成了索引表 Term Dictionary。

但是 Term Dictionary 往往很大,無法完整放入內(nèi)存,這是為了更快的查詢,還需要再給它創(chuàng)建索引,也就是 Term Index 。

ElasticSearch 使用 Burst-Trie 結(jié)構(gòu)來實現(xiàn) Term Index,它是一種前綴樹 Trie 的一種變種,它主要是將后綴進行了壓縮,降低了Trie的高度,從而獲取更好查詢性能。

Term Index 并不需要像 MySQL 的索引一樣,包含所有的 Term,而是包含的是這些 Term 的前綴。它就類似于字典的查詢目錄,可以進行快速定位到 Term Dictionary 的某一位置,然后再從這個位置向后查詢。

綜上, Alice,Alf,Arlan,Bob,Tom 等詞的倒排索引如下所示。綠色部分是 Term Index,藍色部分是 Term Dictionary,紅色部分是 Posting List。

一般來說,Term Index 都是全部緩存在內(nèi)存中,查詢時,先通過其快速定位到 Term Dictionary 對應(yīng)的大致范圍,然后再進行磁盤讀取查找對應(yīng)的 Term,這樣就大大減少了磁盤 I/O 的次數(shù)。

聯(lián)合索引查詢

了解了 ElasticSearch 的倒排索引后,我們再來看看其如何處理復(fù)雜的聯(lián)合索引查詢。比如上述書籍例子中,我們需要查詢評分等于2.2并且作者名稱叫 Tom的書籍。

理論上,我們只需要分別按照 Score 和 Author 字段的倒排索引進行查詢,獲取響應(yīng)的 Posting List,再將其做交集合并即可。

這里又要吐槽一下 MySQL,它是不支持這個合并操作的,它只能按照一個字段的索引進行查詢,然后根據(jù)另外一個字段的條件做內(nèi)存過濾。順便說一下,MySQL 的 join 功能也弱爆了,感興趣的同學(xué)可以了解一下這篇文章

而 ElasticSearch 則支持使用跳表 Skip List和 Bitset 的方式將數(shù)據(jù)集進行合并。

  • 使用 Skip List 結(jié)構(gòu),同時遍歷 Score 和 Author 查詢出來的 Posting List,利用其 Skip List 結(jié)構(gòu),相互跳躍對比,得出合集。

  • 使用 Bitset 結(jié)構(gòu),對 Score 和 Author 查詢出來的 Posting List 的值計算出各自的 Bitset,然后進行 AND 操作。

跳表合并策略

ElasticSearch 在存儲 Posting List 數(shù)據(jù)時,就保存了對應(yīng)的多級跳表結(jié)構(gòu)響應(yīng)的數(shù)據(jù),這也體現(xiàn)了其空間換時間的基本思想。

這里先介紹一下跳表的基本概念,它其實是一種可以進行二分查找的有序鏈表。跳表在原有的有序鏈表上面增加了多級索引,通過索引來實現(xiàn)快速查找。首先在最高級索引上查找最后一個小于當(dāng)前查找元素的位置,然后再跳到次高級索引繼續(xù)查找,直到跳到最底層為止,通過這種方式,加快了查詢的速度。

比如,按照 Score 查出來的 Posting List 為[2,3,4,5,7,9,10,11],按照 Author 查出來的結(jié)果為 [3,8,9,12,13],則二者的跳表結(jié)構(gòu)如下圖所示。

具體合并過程則是先選最短的 posting list,也就是 Author 的結(jié)果集,從其最小的一個 id 開始,將其作為當(dāng)前最大值。然后依次剩余 posting list 中查找大于或等于該值的位置。

比如上述結(jié)果集中,先去 Score 結(jié)果集中查找 3,找到后,就表明 3是二者的合集元素之一;然后再重新開啟一輪,選取 Author 結(jié)果集中 3 的下一個值 8 ,去 Score 結(jié)果集查詢 8,發(fā)現(xiàn)了大于等于 8 的最小的值是 9 ,所以不可能有共同的值 8,然后再去 Author 結(jié)果集查找 9 ,發(fā)現(xiàn)其大于等于 9 的最小值是 12,所以再去 Score 結(jié)果集中查找大于等于 12的值,發(fā)現(xiàn)并不存在;最終得出二者的合集就只有[3]。

在查詢過程中,每個 posting list 都可以根據(jù)當(dāng)前 id 通過 skip list 快速跳過不符合的 id 值,加速整個合并取交集的過程。

ElasticSearch 對于較長的 posting list 也會使用 Frame Of Reference 進行壓縮編碼,減少了磁盤占用,減少了索引尺寸。有關(guān)具體存儲結(jié)構(gòu)的實現(xiàn)我們后續(xù)再進行細聊。

Bitset 合并策略

ElasticSearch除了使用 skipList 來進行數(shù)據(jù)磁盤讀取時的合并操作外,還會將一些查詢條件對應(yīng)的結(jié)果集 posting list 進行內(nèi)存緩存,也就是所謂的 Filter Cache,為了后續(xù)再次復(fù)用。

為了減少內(nèi)存緩存所消耗的內(nèi)存空間大小,ElasticSearch 沒有使用單純的數(shù)組和 bitset 來存儲 posting list,而是使用要壓縮效率更高的 Roaring Bitmap。

我們可以先來講一下單純數(shù)組或 bitset 數(shù)據(jù)結(jié)構(gòu)為什么并不使用。比如如下一道較為常見的面試題目:

給定含有40億個不重復(fù)的位于[0, 2^32 - 1]區(qū)間內(nèi)的整數(shù)的集合,如何快速判定某個數(shù)是否在該集合內(nèi)?

如果我們要使用 unsigned long 數(shù)組來存儲它的話,也就需要消耗 40億 * 32 位 = 160 Byte,大致是 16000 MB。

如果要使用位圖 Bitset 來存儲的話,即某個數(shù)位于原集合內(nèi),就將它對應(yīng)的位圖內(nèi)的比特置為1,否則保持為0。這樣只需要消耗 2 ^ 32 位 = 512 MB,這可只有原來的 3.2 % 左右。

但是,Bitset 也有其缺陷,也就是稀疏存儲的問題,比如上述集合并不是 40億,而是只有2,3個,那么 Bitset 中只有少數(shù)幾位是1,其他位都是 0,但是它仍然占用了 512 MB。

而 RoaringBitmap 就是為了解決稀疏存儲的問題。下圖就是 RoaringBitmap 的基本原理示意圖。

首先,如上圖所示,計算出32位無符號整數(shù)和 65536 的除數(shù)和余數(shù)。其含義表示,將32位無符號整數(shù)按照高16位分桶,即最多可能有2^16=65536個桶,術(shù)語懲治為 container。存儲數(shù)據(jù)時,按照數(shù)據(jù)的高16位找到 container(找不到就會新建一個),再將低16位放入container中。也就是說,一個 RoaringBitmap 就是很多container的集合。

然后 container 內(nèi)具體的存儲結(jié)構(gòu)要根據(jù)存入其內(nèi)數(shù)據(jù)的基數(shù)來決定。

  • 基數(shù)小于 2 ^ 12 次方即 4096時,使用unsigned short類型的有序數(shù)組來存儲,最大消耗空間就是  8 KB。

  • 基數(shù)大于 4096 時,則使用大小為 2 ^ 16 次方的普通 bitset 來存儲,固定消耗 8 KB。當(dāng)然,有些時候也會對 bitset 進行行程長度編碼(RLE)壓縮,進一步減少空間占用。

ElasticSearch 就是使用 Roaring Bitmap 來緩存不同條件查詢出來的 posting list,然后再進行與操作計算出最終結(jié)果集。

后記

至此,我們也算了解了 ElasticSearch 為什么比 MySQL 更適合復(fù)雜條件查詢,但是有好就有弊,因為為了查詢做了這么多的準(zhǔn)備工作,ElasticSearch 的插入速度就會慢于 MySQL,而且數(shù)據(jù)存入ES后并不是立馬就能檢索到

歡迎持續(xù)關(guān)注歷小冰,后續(xù)繼續(xù)為大家分享 MySQL、Redis 和 ElasticSearch 等數(shù)據(jù)庫相關(guān)的原理和實踐經(jīng)驗。

免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺僅提供信息存儲服務(wù)。文章僅代表作者個人觀點,不代表本平臺立場,如有問題,請聯(lián)系我們,謝謝!

本站聲明: 本文章由作者或相關(guān)機構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

LED驅(qū)動電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: 驅(qū)動電源

在工業(yè)自動化蓬勃發(fā)展的當(dāng)下,工業(yè)電機作為核心動力設(shè)備,其驅(qū)動電源的性能直接關(guān)系到整個系統(tǒng)的穩(wěn)定性和可靠性。其中,反電動勢抑制與過流保護是驅(qū)動電源設(shè)計中至關(guān)重要的兩個環(huán)節(jié),集成化方案的設(shè)計成為提升電機驅(qū)動性能的關(guān)鍵。

關(guān)鍵字: 工業(yè)電機 驅(qū)動電源

LED 驅(qū)動電源作為 LED 照明系統(tǒng)的 “心臟”,其穩(wěn)定性直接決定了整個照明設(shè)備的使用壽命。然而,在實際應(yīng)用中,LED 驅(qū)動電源易損壞的問題卻十分常見,不僅增加了維護成本,還影響了用戶體驗。要解決這一問題,需從設(shè)計、生...

關(guān)鍵字: 驅(qū)動電源 照明系統(tǒng) 散熱

根據(jù)LED驅(qū)動電源的公式,電感內(nèi)電流波動大小和電感值成反比,輸出紋波和輸出電容值成反比。所以加大電感值和輸出電容值可以減小紋波。

關(guān)鍵字: LED 設(shè)計 驅(qū)動電源

電動汽車(EV)作為新能源汽車的重要代表,正逐漸成為全球汽車產(chǎn)業(yè)的重要發(fā)展方向。電動汽車的核心技術(shù)之一是電機驅(qū)動控制系統(tǒng),而絕緣柵雙極型晶體管(IGBT)作為電機驅(qū)動系統(tǒng)中的關(guān)鍵元件,其性能直接影響到電動汽車的動力性能和...

關(guān)鍵字: 電動汽車 新能源 驅(qū)動電源

在現(xiàn)代城市建設(shè)中,街道及停車場照明作為基礎(chǔ)設(shè)施的重要組成部分,其質(zhì)量和效率直接關(guān)系到城市的公共安全、居民生活質(zhì)量和能源利用效率。隨著科技的進步,高亮度白光發(fā)光二極管(LED)因其獨特的優(yōu)勢逐漸取代傳統(tǒng)光源,成為大功率區(qū)域...

關(guān)鍵字: 發(fā)光二極管 驅(qū)動電源 LED

LED通用照明設(shè)計工程師會遇到許多挑戰(zhàn),如功率密度、功率因數(shù)校正(PFC)、空間受限和可靠性等。

關(guān)鍵字: LED 驅(qū)動電源 功率因數(shù)校正

在LED照明技術(shù)日益普及的今天,LED驅(qū)動電源的電磁干擾(EMI)問題成為了一個不可忽視的挑戰(zhàn)。電磁干擾不僅會影響LED燈具的正常工作,還可能對周圍電子設(shè)備造成不利影響,甚至引發(fā)系統(tǒng)故障。因此,采取有效的硬件措施來解決L...

關(guān)鍵字: LED照明技術(shù) 電磁干擾 驅(qū)動電源

開關(guān)電源具有效率高的特性,而且開關(guān)電源的變壓器體積比串聯(lián)穩(wěn)壓型電源的要小得多,電源電路比較整潔,整機重量也有所下降,所以,現(xiàn)在的LED驅(qū)動電源

關(guān)鍵字: LED 驅(qū)動電源 開關(guān)電源

LED驅(qū)動電源是把電源供應(yīng)轉(zhuǎn)換為特定的電壓電流以驅(qū)動LED發(fā)光的電壓轉(zhuǎn)換器,通常情況下:LED驅(qū)動電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: LED 隧道燈 驅(qū)動電源
關(guān)閉