當前位置:首頁 » 編程語言 » MongoDB統計類型的SQL
擴展閱讀
webinf下怎麼引入js 2023-08-31 21:54:13
堡壘機怎麼打開web 2023-08-31 21:54:11

MongoDB統計類型的SQL

發布時間: 2023-06-14 19:34:38

1. 雲上MongoDB常見索引問題及最優索引規則大全

本文干貨較多,建議收藏學習。先將文章結構速覽奉上:

一、背景

二、MongoDB執行計劃

2.1 queryPlanner信息

2.2 executionStats信息

2.3 allPlansExecution信息

三、雲上用戶建索引常見問題及優化方法

3.1 等值類查詢常見問題及優化方法

3.1.1 同一類查詢創建多個索引問題

3.1.2 多欄位等值查詢組合索引順序非最優

3.1.3 最左原則包含關系引起的重復索引

3.1.4 唯一欄位和其他欄位組合引起的無用重復索引

3.2 非等值類查詢常見問題及優化方法

3.2.1 非等值組合查詢索引不合理創建

3.2.2 等值+非等值組合查詢索引欄位順序不合理

3.2.3 不同類型非等值查詢優先順序問題

3.3 OR類查詢常見問題及優化方法

3.3.1 普通OR類查詢優化方法

3.3.2 復雜OR類查詢優化方法

3.4 SORT類排序查詢常見問題及優化方法

3.4.1 單欄位正反序排序查詢引起的重復索引

3.4.2 多欄位排序查詢正反序問題引起索引無效

3.4.3 等值查詢+多欄位排序組合查詢

3.4.4 等值查詢+非等值查詢+SORT排序查詢

3.4.5 OR+SORT組合排序查詢

3.5 無用索引優化方法

四、MongoDB不同類型查詢最優索引總結

騰訊雲MongoDB當前已服務於 游戲 、電商、社交、教育、新聞資訊、金融、物聯網、軟體服務、 汽車 出行、音視頻等多個行業。

騰訊MongoDB團隊在配合用戶分析問題過程中,發現 雲上用戶存在如下索引共性問題 ,主要集中在如下方面:

本文 重點分析總結騰訊雲上用戶索引創建不合理相關的問題 ,通過本文可以學習到MongoDB的以下知識點:

本文總結的 《最優索引規則創建大全》 不僅僅適用於MongoDB,很多規則 同樣適用於Mysql等關系型資料庫

判斷索引選擇及不同索引執行傢伙信息可以通過explain操作獲取, MongoDB通過explain來獲取SQL執行過程信息 ,當前持續explain的請求命令包含以下幾種:

aggregate, count, distinct, find, findAndModify, delete, mapRece, and update。

詳見explain官網鏈接:

https://docs.MongoDB.com/manual/reference/command/explain/

explain可以攜帶以下幾個參數信息,各參數信息功能如下:

2.1 queryPlanner信息

獲取MongoDB查詢優化器選擇的最優索引和拒絕掉的非最優索引,並給出各個候選索引的執行階段信息,queryPlanner輸出信息如下:

queryPlanner輸出主要包括如下信息:

parsedQuery信息

內核對查詢條件進行序列化,生成一棵expression tree信息,便於候選索引查詢匹配。

winningPlan信息

rejectedPlans信息

輸出信息和winningPlan類似,記錄這些拒絕掉索引的執行stage信息。

2.2 executionStats信息

explain的executionStats參數除了提供上面的queryPlanner信息外,還提供了最優索引的執行過程信息,如下:

上面是通過executionStats獲取執行過程的詳細信息,其中欄位信息較多,平時分析索引問題最常用的幾個欄位如下:

executionStats輸出欄位較多,其他欄位將在後續《MongoDB內核index索引模塊實現原理》中進行進一步說明。

在實際分析索引問題是否最優的時候,主要查看以下三個統計項:

executionStats.totalKeysExamined

executionStats.totalDocsExamined

executionStats .nReturned

如果存在以下情況則說明索引存在問題,可能索引不是最優的:

1. executionStats.totalKeysExamine遠大於executionStats .nReturned

2. executionStats. totalDocsExamined遠大於executionStats .nReturned

2.3 allPlansExecution信息

allPlansExecution參數對應輸出信息和executionStats輸出信息類似,只是多了所有候選索引(包括reject拒絕的非最優索引)的執行過程,這里不再詳述。

2.4 總結

從上面的幾個explain執行計劃參數輸出信息可以看出,各個參數的功能各不相同,總結如下:

queryPlanner

輸出索引的候選索引,包括最優索引及其執行stage過程(winningPlan)+其他非最優候選索引及其執行stage過程。

注意: queryPlanner沒有真正在表中執行整個SQL,只做了查詢優化器獲取候選索引過程,因此可以很快返回。

executionStats

相比queryPlanner參數,executionStats會記錄查詢優化器根據所選最優索引執行SQL的整個過程信息,會真正執行整個SQL。

allPlansExecution

和executionStats類似,只是多了所有候選索引的執行過程。

在和用戶一起優化騰訊雲上MongoDB集群索引過程中,以及和頭部用戶的交流中發現很多用戶對如何創建最優索引有較為嚴重的錯誤認識,並且很多是絕大部分用戶的共性問題,因此在本文中將這些問題匯總如下:

3.1 等值類查詢常見問題及優化方法

如下三個查詢:

用戶創建了如下3個索引:

{a:1, b:1, c:1}

{b:1, a:1, c:1}

{c:1, a:1, b:1}

實際上這3個查詢屬於同一類查詢,只是查詢欄位順序不一樣,因此只需創建任一個索引即可滿足要求。驗證過程如下:

從上面的expalin輸出可以看出,3個查詢都走向了同一個索引。

例如test表有多條數據,每條數據有3個欄位,分別為a、b、c。其中a欄位有10種取值,b欄位有100種取值,c欄位有1000種取值,稱為各個欄位值的 「區分度」

用戶查詢條件為db.test.find({"a":"xxx", "b":"xxx", "c":"xxx"}),創建的索引為{a:1, b:1, c:1}。如果只是針對這個查詢,該查詢可以創建a,b,c三欄位的任意組合,並且其SQL執行代價一樣,通過hint強制走不通索引,驗證過程如下:

從上面的執行計劃可以看出,多欄位等值查詢各個欄位的組合順序對應執行計劃代價一樣。絕大部分用戶在創建索引的時候,都是直接按照查詢欄位索引組合對應欄位。

但是,單就這一個查詢,這里有個不成文的建議,把區分度更高的欄位放在組合索引左邊,區分度低的欄位放到右邊。這樣做有個好處,資料庫組合索引遵從最左原則,就是當其他查詢裡面帶有區分度最高的欄位時,就可以快速排除掉更多不滿足條件的數據。

例如用戶有如下兩個查詢:

用戶創建了如下兩個索引:

{b:1, c:1}

{a:1,b:1,c:1}

這兩個查詢中,查詢2中包含有查詢1中的欄位,因此可以用一個索引來滿足這兩個查詢要求,按照最左原則,查詢1欄位放左邊即可,該索引可以優化為:b,c欄位索引+a欄位索引,b,c欄位順序可以根據區分排序,加上c欄位區分度比b高,則這兩個查詢可以合並為一個{c:1, b:1, a:1}。兩個查詢可以走同一個索引驗證過程如下:

從上面輸出可以看出,這兩個查詢都走了同一個索引。

例如用戶有以下兩個查詢:

用戶為這兩個查詢創建了兩個索引,{a:1, b:1}和{a:1, c:1},但是a欄位取值是唯一的,因此這兩個查詢中a以外的欄位無用,一個{a:1}索引即可滿足要求。

3.2 非 等值類查詢常見索引錯誤創建方法及如何創建最優索引

假設用戶有如下查詢:

a,c兩個欄位都是非等值查詢,很多用戶直接添加了{a:1, c:1}索引,實際上多個欄位的非等值查詢,只有最左邊的欄位才能走索引,例如這里只會走a欄位索引,驗證過程如下:

從上面執行計劃可以看出,索引數據掃描了10行(也就是a欄位滿足a:{$gte:1}條件的數據多少),但是實際上只返回了4條滿足{a:{$gte:1}, c:{$lte:1}}條件的數據,可以看出c欄位無法做索引。

同理,當查詢中包含多個欄位的范圍查詢的適合,除了最左邊第一個欄位可以走索引,其他欄位都無法走索引。因此,上面例子中的查詢候選索引為{a:1}或者{b:1}中任何一個就可以了,組合索引中欄位太多會佔用更多存儲成本、同時佔用更多IO資源引起寫放大。

例如下面查詢:

如上查詢,d欄位為非等值查詢,e欄位為等值查詢,很多用戶遇到該類查詢直接創建了{d:1, e:1}索引,由於d欄位為非等值查詢,因此e欄位無法走索引,驗證過程如下:

從上面驗證過程可以看出,等值類和非等值類組合查詢對應組合索引,最優索引應該優先把等值查詢放到左邊,上面查詢對應最優索引{e:1, d:1}

前面用到的非等值查詢操作符只提到了比較類操作符,實際上非等值查詢還有其他操作符。常用非等值查詢包括:$gt、$gte、$lt、$lte、$in、$nin、$ne、$exists、$type等,這些非等值查詢在絕大部分情況下存在如下優先順序:

從上到下優先順序更高,例如下面的查詢:

如上,該查詢等值部分查詢最優索引{a:1, b:1}(假設a區分度比b高);非等值部分,因為$in操作符優先順序最高,排他性更好,加上多個欄位非等值查詢只會有一個欄位走索引,因此非等值部分最優索引為{g:1}。

最終該查詢最優索引為:」等值部分最優索引」與」非等值部分最優索引」拼接,也就是{a:1,b:1, g:1}

3.3 OR類查詢常見索引錯誤創建方法及如何創建最優索引

例如下面的OR查詢:

該查詢很多用戶直接創建了{b:1, d:1, c:1, a:1},用戶創建該索引後,發現用戶還是全表掃描。

OR類查詢需要給數組中每個查詢添加索引,例如上面or數組中實際包含{ b: 0, d:0 }和 {"c":1, "a":{$gte:4}}查詢,需要創建兩個查詢的最優索引,也就是{b:1, d:1}和{c:1, a:1},執行計劃驗證過程如下(該測試表總共10條數據):

從上面執行計劃可以看出,如果該OR類查詢走{b:1, d:1, c:1, a:1}索引,則實際上做了全表掃描。如果同時創建{b:1, d:1}、{c:1, a:1}索引,則直接走兩個索引,其執行key和doc掃描行數遠遠小於全表掃描。

這里在提升一下OR查詢難度,例如下面的查詢:

上面的查詢可以轉換為如下兩個查詢:

如上圖,查詢1拆分後的兩個查詢2和查詢3組成or關系,因此對應最優索引需要創建兩個,分表是:{f:1, g:1, b:1, d:1} 和 {f:1, g:1, b:1, d:1}。對應執行計劃如下:

同理,不管怎麼增加難度,OR查詢最終可轉換為多個等值、非等值或者等值與非等值組合類查詢,通過如上變換最終可以起到舉一反三的作用。

說明:這個例子中可能在一些特殊數據分布場景,最優索引也可能是{f:1, g:1}或者{f:1, g:1, b:1, d:-1}或者{ f:1, g:1, c:1, a:1},這里我們只考慮大部分通用場景。

3.4 SORT類排序查詢常見索引錯誤創建方法及如何創建最優索引

例如用戶有以下兩個查詢:

這兩個查詢都不帶條件,排序方式不一樣,因此很多創建了兩個索引{a:1}和{a:-1},實際上這兩個索引中的任何一個都可以滿足兩種查詢要求,驗證過程如下:

假設有如下查詢:

其中a欄位為正序,b欄位為反序排序,很多用戶直接創建{a:1, b:1}索引,這時候b欄位內容就存在內存排序情況。多欄位排序索引,如果沒有攜帶查詢條件,則最優索引即為排序欄位對應索引,這里切記保持每個欄位得正反序和sort完全一致,否則可能存在部分欄位內存排序的情況,執行計劃驗證過程如下:

例如如下查詢:

該類查詢很多人直接創建{a:1, b:1, c:1, d:1},結果造成內存排序。這種組合查詢最優索引=「多欄位等值查詢最優索引_多欄位排序類組合最優索引」,例如該查詢:

{ "a" : 3, "b" : 1}等值查詢假設a區分度比b高,則對應最優索引為:{a:1, b:1}

{ c:-1, d:1}排序類查詢最優索引保持正反序一致,也就是:{ c:-1, d:1}

因此整個查詢就是這兩個查詢對應最優索引拼接,也就是{a:1, b:1, c:-1, d:1},對應執行計劃過程驗證如下:

假設有下面的查詢:

騰訊雲很多用戶看到該查詢直接創建{a:1, b:1, c:1, d:-1, e:1}索引,發現存在內存排序。等值+非等值+sort排序組合查詢,由於非等值查詢右邊的欄位不能走索引,因此如果把d, e放到c的右邊,則d,e欄位索引無效。

等值+非等值+sort排序最優索引組合欄位順序為:等值_sort排序_非等值,因此上面查詢最優索引為:{a:1, b:1, d:-1, e:1, c:1}。執行計劃驗證過程如下:

例如如下查詢:

上面組合很多人直接創建{b:1, d:1, c:1, a:1, e:1},該索引創建後還是會掃表和內存排序,實際上OR+SORT組合查詢可以轉換為下面兩個查詢:

所以這個復雜查詢就可以拆分為等值組合查詢+sort排序查詢,拆分為上面的兩個查詢,這樣我們只需要同時創建查詢2和查詢3對應最優索引即可。該查詢最終拆分後對應最優索引需要添加如下兩個:

{b:1, d:1, e:-1}和{c:1, a:1, e:-1}

非最優索引和最優索引執行計劃驗證過程如下:

OR+SORT類查詢,最終可以《參考前面的OR類查詢常見索引錯誤創建方法》把OR查詢轉換為多個等值、非等值或者等值與非等值組合查詢,然後與sort排序對應索引欄位拼接。例如下面查詢:

拆分後的兩個查詢組成or關系,如下:

如上,查詢1 = or: [查詢2, 查詢3],因此只需要創建查詢2和查詢3兩個最優索引即可滿足查詢1要求,查詢2和查詢3最優索引可以參考前面《or類查詢常見索引錯誤創建方法》,該查詢最終需要創建如下兩個索引:

{f:1, g:1, b:1, d:1, e:-1}和{ f:1, g:1, c:1, a:1, e:-1}

說明:這個例子中可能在一些特殊數據分布場景,最優索引也可能是{f:1, g:1}或者{f:1, g:1, b:1, d:1, e:-1}或者{ f:1, g:1, c:1, a:1, e:-1},這里我們只考慮通用場景。

3.5 避免創建太多無用索引及無用索引分析方法

在騰訊雲上,我們還發現另外一個問題,很多實例存在大量無用索引,無用索引會引起以下問題:

存儲成本增加

沒增加一個索引,MongoDB內核就會創建一個index索引文件,記錄該表的索引數據,造成存儲成本增加。

影響寫性能

用戶沒寫入一條數據,就會在對應索引生成一條索引KV,實現索引與數據的一一對應,索引KV數據寫入Index索引文件過程加劇寫入負載。

影響讀性能

MongoDB內核查詢優化器原理是通過候選索引快速定位到滿足條件的數據,然後采樣評分。如果滿足條件的候選索引越多,整個評分過程就會越長,增加內核選擇最優索引的流程。

下面以一個真實線上實例為例,說明如何找出無用索引:

MongoDB默認提供有索引統計命令來獲取各個索引命中的次數,該命令如下:

該聚合輸出中的幾個核心指標信息如下表:

上表中的ops代表命中次數,如果命中次數為0或者很小,說明該索引很少被選為最優索引使用,因此可以認為是無用索引,可以考慮刪除。

說明:

本文總結的《最優索引規則大全》中的規則適用於絕大部分查詢場景,但是一些特殊數據分布場景可能會有一定偏差,請根據實際數據分布進行查詢計劃分析。

DBbrain for MongoDB

最後,本文中所介紹的優化原理即將集成到騰訊雲DBbrain for MongoDB的智能索引推薦(規則+代價計算)功能中,屆時可幫助用戶一鍵優化索引,無需親自反復推敲驗證,歡迎體驗。

騰訊雲MongoDB當前服務於 游戲 、電商、社交、教育、新聞資訊、金融、物聯網、軟體服務等多個行業;MongoDB團隊(簡稱CMongo)致力於對開源MongoDB內核進行深度研究及持續性優化(如百萬庫表、物理備份、免密、審計等),為用戶提供高性能、低成本、高可用性的安全資料庫存儲服務。後續持續分享MongoDB在騰訊內部及外部的典型應用場景、踩坑案例、性能優化、內核模塊化分析。

叮咚買菜自建MangoDB上騰訊雲實踐

2. 怎麼將mongodb裡面的sql操作記錄下來

准備
在此之前,我們先在我們的資料庫中插入10萬條數據。數據的格式是這樣的:
?

1
2
3
4
5
6

{
"name":"your name",
"age":22,
"gender":"male",
"grade":2
}

explain
explain方法是用來查看db.collecion.find()的一些查詢信息的。例如:
?

1

db.collectionName.find().explain()

explain方法有個可選的參數verbose,是個字元串,他表示的是verbose的模式。一共分為3種模式:
queryPlanner:默認參數,詳細說明查詢優化器選擇的計劃並列出

3. MongoDB是什麼,怎麼用看完你就知道了

MongoDB是一款為web應用程序和互聯網基礎設施設計的資料庫管理系統。沒錯MongoDB就是資料庫,是NoSQL類型的資料庫。

(1)MongoDB提出的是文檔、集合的概念,使用BSON(類JSON)作為其數據模型結構,其結構是面向對象的而不是二維表,存儲一個用戶在MongoDB中是這樣子的。

使用這樣的數據模型,使得MongoDB能在生產環境中提供高讀寫的能力,吞吐量較於mysql等SQL資料庫大大增強。

(2)易伸縮,自動故障轉移。易伸縮指的是提供了分片能力,能對數據集進行分片,數據的存儲壓力分攤給多台伺服器。自動故障轉移是副本集的概念,MongoDB能檢測主節點是否存活,當失活時能自動提升從節點為主節點,達到故障轉移。

(3)數據模型因為是面向對象的,所以可以表示豐富的、有層級的數據結構,比如博客系統中能把「評論」直接懟到「文章「的文檔中,而不必像myqsl一樣創建三張表來描述這樣的關系。

(1)文檔數據類型

SQL類型的資料庫是正規化的,可以通過主鍵或者外鍵的約束保證數據的完整性與唯一性,所以SQL類型的資料庫常用於對數據完整性較高的系統。MongoDB在這一方面是不如SQL類型的資料庫,且MongoDB沒有固定的Schema,正因為MongoDB少了一些這樣的約束條件,可以讓數據的存儲數據結構更靈活,存儲速度更加快。

(2)即時查詢能力

MongoDB保留了關系型資料庫即時查詢的能力,保留了索引(底層是基於B tree)的能力。這一點汲取了關系型資料庫的優點,相比於同類型的NoSQL redis 並沒有上述的能力。

(3)復制能力

MongoDB自身提供了副本集能將數據分布在多台機器上實現冗餘,目的是可以提供自動故障轉移、擴展讀能力。

(4)速度與持久性

MongoDB的驅動實現一個寫入語義 fire and forget ,即通過驅動調用寫入時,可以立即得到返回得到成功的結果(即使是報錯),這樣讓寫入的速度更加快,當然會有一定的不安全性,完全依賴網路。

MongoDB提供了Journaling日誌的概念,實際上像mysql的bin-log日誌,當需要插入的時候會先往日誌裡面寫入記錄,再完成實際的數據操作,這樣如果出現停電,進程突然中斷的情況,可以保障數據不會錯誤,可以通過修復功能讀取Journaling日誌進行修復。

(5)數據擴展

MongoDB使用分片技術對數據進行擴展,MongoDB能自動分片、自動轉移分片裡面的數據塊,讓每一個伺服器裡面存儲的數據都是一樣大小。

MongoDB核心伺服器主要是通過mongod程序啟動的,而且在啟動時不需對MongoDB使用的內存進行配置,因為其設計哲學是內存管理最好是交給操作系統,缺少內存配置是MongoDB的設計亮點,另外,還可通過mongos路由伺服器使用分片功能。

MongoDB的主要客戶端是可以交互的js shell 通過mongo啟動,使用js shell能使用js直接與MongoDB進行交流,像使用sql語句查詢mysql數據一樣使用js語法查詢MongoDB的數據,另外還提供了各種語言的驅動包,方便各種語言的接入。

mongomp和mongorestore,備份和恢復資料庫的標准工具。輸出BSON格式,遷移資料庫。

mongoexport和mongoimport,用來導入導出JSON、CSV和TSV數據,數據需要支持多格式時有用。mongoimport還能用與大數據集的初始導入,但是在導入前順便還要注意一下,為了能充分利用好mongoDB通常需要對數據模型做一些調整。

mongosniff,網路嗅探工具,用來觀察發送到資料庫的操作。基本就是把網路上傳輸的BSON轉換為易於人們閱讀的shell語句。

因此,可以總結得到,MongoDB結合鍵值存儲和關系資料庫的最好特性。因為簡單,所以數據極快,而且相對容易伸縮還提供復雜查詢機制的資料庫。MongoDB需要跑在64位的伺服器上面,且最好單獨部署,因為是資料庫,所以也需要對其進行熱備、冷備處理。

因為本篇文章不是API手冊,所有這里對shell的使用也是基礎的介紹什麼功能可以用什麼語句,主要是為了展示使用MongoDB shell的方便性,如果需要知道具體的MongoDB shell語法可以查閱官方文檔。

創建資料庫並不是必須的操作,資料庫與集合只有在第一次插入文檔時才會被創建,與對數據的動態處理方式是一致的。簡化並加速開發過程,而且有利於動態分配命名空間。如果擔心資料庫或集合被意外創建,可以開啟嚴格模式。

以上的命令只是簡單實例,假設如果你之前沒有學習過任何資料庫語法,同時開始學sql查詢語法和MongoDB 查詢語法,你會發現哪一個更簡單呢?如果你使用的是java驅動去操作MongoDB,你會發現任何的查詢都像Hibernate提供出來的查詢方式一樣,只要構建好一個查詢條件對象,便能輕松查詢(接下來會給出示例),博主之前熟悉ES6,所以入手MongoDB js shell完成沒問題,也正因為這樣簡潔,完善的查詢機制,深深的愛上了MongoDB。

使用java驅動鏈接MongoDB是一件非常簡單的事情,簡單的引用,簡單的做增刪改查。在使用完java驅動後我才發現spring 對MongoDB 的封裝還不如官方自身提供出來的東西好用,下面簡單的展示一下使用。

這里只舉例了簡單的鏈接與簡單的MongoDB操作,可見其操作的容易性。使用驅動時是基於TCP套接字與MongoDB進行通信的,如果查詢結果較多,恰好無法全部放進第一伺服器中,將會向伺服器發送一個getmore指令獲取下一批查詢結果。

插入數據到伺服器時間,不會等待伺服器的響應,驅動會假設寫入是成功的,實際是使用客戶端生成對象id,但是該行為可以通過配置配置,可以通過安全模式開啟,安全模式可以校驗伺服器端插入的錯誤。

要清楚了解MongoDB的基本數據單元。在關系型資料庫中有帶列和行的數據表。而MongoDB數據的基本單元是BSON文檔,在鍵值中有指向不定類型值的鍵,MongoDB擁有即時查詢,但不支持聯結操作,簡單的鍵值存儲只能根據單個鍵來獲取值,不支持事務,但支持多種原子更新操作。

如讀寫比是怎樣的,需要何種查詢,數據是如何更新的,會不會存在什麼並發問題,數據結構化的程度是要求高還是低。系統本身的需求決定mysql還是MongoDB。

在關於schema 的設計中要注意一些原則,比如:

資料庫是集合的邏輯與物理分組,MongoDB沒有提供創建資料庫的語法,只有在插入集合時,資料庫才開始建立。創建資料庫後會在磁碟分配一組數據文件,所有集合、索引和資料庫的其他元數據都保存在這些文件中,查閱資料庫使用磁碟狀態可通過。

集合是結構上或概念上相似得文檔的容器,集合的名稱可以包含數字、字母或 . 符號,但必須以字母或數字開頭,完全。

限定集合名不能超過128個字元,實際上 . 符號在集合中很有用,能提供某種虛擬命名空間,這是一種組織上的原則,和其他集合是一視同仁的。在集合中可以使用。

其次是鍵值,在MongoDB裡面所有的字元串都是UTF-8類型。數字類型包括double、int、long。日期類型都是UTC格式,所以在MongoDB裡面看到的時間會比北京時間慢8小時。整個文檔大小會限制在16m以內,因為這樣可以防止創建難看的數據類型,且小文檔可以提升性能,批量插入文檔理想數字范圍是10~200,大小不能超過16MB。

(1)索引能顯著減少獲取文檔的所需工作量,具體的對比可以通過 .explain()方法進行對比

(2)解析查詢時MongoDB通過最優計劃選擇一個索引進行查詢,當沒有最適合索引時,會先不同的使用各個索引進行查詢,最終選出一個最優索引做查詢

(3)如果有一個a-b的復合索引,那麼僅針對a的索引是冗餘的

(4)復合索引里的鍵的順序是很重要的

(1)單鍵索引

(2)復合索引

(3)唯一性索引

(4)稀疏索引

如索引的欄位會出現null的值,或是大量文檔都不包含被索引的鍵。

如果數據集很大時,構建索引將會花費很長的時間,且會影響程序性能,可通過

當使用 mongorestore 時會重新構建索引。當曾經執行過大規模的刪除時,可使用

對索引進行壓縮,重建。

(1)查閱慢查詢日誌

(2)分析慢查詢

注意新版本的MongoDB 的explain方法是需要參數的,不然只顯示普通的信息。

本節同樣主要簡單呈現MongoDB副本集搭建的簡易性,與副本集的強壯性,監控容易性

提供主從復制能力,熱備能力,故障轉移能力

實際上MongoDB對副本集的操作跟mysql主從操作是差不多的,先看一下mysql的主從數據流動過程

而MongoDB主要依賴的日誌文件是oplog

寫操作先被記錄下來,添加到主節點的oplog里。與此同時,所有從結點復制oplog。首先,查看自己oplog里最後一條的時間戳;其次,查詢主節點oplog里所有大於此時間戳的條目;最後,把那些條目添加到自己的oplog里並應用到自己的庫里。從節點使用長輪詢立即應用來自主結點oplog的新條目。

當遇到以下情況,從節點會停止復制

local資料庫保存了所有副本集元素據和oplog日誌

可以使用以下命令查看復制情況

每個副本集成員每秒鍾ping一次其他所有成員,可以通過rs.status()看到節點上次的心跳檢測時間戳和 健康 狀況。

這個點沒必要過多描述,但是有一個特殊場景,如果從節點和仲裁節點都被殺了,只剩下主節點,他會把自己降級成為從節點。

如果主節點的數據還沒有寫到從庫,那麼數據不能算提交,當該主節點變成從節點時,便會觸發回滾,那些沒寫到從庫的數據將會被刪除,可以通過rollback子目錄中的BSON文件恢復回滾的內容。

(1)使用單節點鏈接

只能鏈接到主節點,如果鏈接到從節點的話,會被拒絕寫入操作,但是如果沒有使用安全模式,因為mongo的fire and forget 特性,會把拒絕寫入的異常給吃掉。

(2)使用副本集方式鏈接

能根據寫入的情況自動進行故障轉移,但是當副本集進行新的選舉時,還是會出現故障,如果不使用安全模式,依舊會出現寫不進去,但現實成功的情況。

分片是資料庫切分的一個概念實現,這里也是簡單總結為什麼要使用分片以及分片的原理,操作。

當數據量過大,索引和工作數據集佔用的內存就會越來越多,所以需要通過分片負載來解決這個問題

(1)分片組件

(2)分片的核心操作

分片一個集合:分片是根據一個屬性的范圍進行劃分的,MongoDB使用所謂的分片鍵讓每個文檔在這些范圍里找到自己的位置

塊:是位於一個分片中的一段連續的分片鍵范圍,可以理解為若干個塊組成分片,分片組成MongoDB的全部數據

(3)拆分與遷移

塊的拆分:初始化時只有一個塊,達到最大塊尺寸64MB或100000個文檔就會觸發塊的拆分。把原來的范圍一分為二,這樣就有了兩個塊,每個塊都有相同數量的文檔。

遷移:當分片中的數據大小不一時會產生遷移的動作,比如分片A的數據比較多,會將分片A裡面的一些塊轉移到分片B裡面去。分片集群通過在分片中移動塊來實現均衡,是由名為均衡器的軟體進程管理的,任務是確保數據在各個分片中保持均勻分布,當集群中擁有塊最多的分片與擁有塊最少分片的塊差大於8時,均衡器就會發起一次均衡處理。

啟動兩個副本集、三個配置伺服器、一個mongos進程

配置分片

(1)分片查詢類型

(2)索引

分片集合只允許在_id欄位和分片鍵上添加唯一性索引,其他地方不行,因為這需要在分片間進行通信,實施起來很復雜。

當創建分片時,會根據分片鍵創建一個索引。

(1)分片鍵是不可修改的、分片鍵的選擇非常重要

(2)低效的分片鍵

(3)理想的分片鍵

(1)部署拓撲

根據不同的數據中心劃分

這里寫圖片描述

(2)最低要求

(3)配置的注意事項

需要估計集群大小,可使用以下命令對現有集合進行分片處理

(4)備份分片集群

備份分片時需要停止均衡器

(1)部署架構

使用64位機器、32位機器會制約mongodb的內存,使其最大值為1.5GB

(2)cpu

mongodb 只有當索引和工作集都可放入內存時,才會遇到CPU瓶頸,CPU在mongodb使用中的作用是用來檢索數據,如果看到CPU使用飽和的情況,可以通過查詢慢查詢日誌,排查是不是查詢的問題導致的,如果是可以通過添加索引來解決問題

mongodb寫入數據時會使用到CPU,但是mongodb寫入時間一次只用到一個核,如果有頻繁的寫入行為,可以通過分片來解決這個問題

(3)內存

大內存是mongodb的保障,如果工作集大小超過內存,將會導致性能下降,因為這將會增加數據載入入內存的動作

(4)硬碟

mongodb默認每60s會與磁碟強制同步一次,稱為後台刷新,會產生I/O操作。在重啟時mongodb會將磁碟裡面的數據載入至內存,高速磁碟將會減少同步的時間

(5)文件系統

使用ext4 和 xfs 文件系統

禁用最後訪問時間

(6)文件描述符

linux 默認文件描述符是1024,需要大額度的提升這個額度

(7)時鍾

mongodb各個節點伺服器之間使用ntp伺服器

(1)綁定IP

啟動時使用 - -bind_ip 命令

(2)身份驗證

啟動時使用 - -auth 命令

(3)副本集身份認證

使用keyFile,注意keyFile文件的許可權必須是600,不然會啟動不起來

(1)拓撲結構

搭建副本集至少需要兩個節點,其中仲裁結點不需要有自己的伺服器

(2)Journaling日誌

寫數據時會先寫入日誌,而此時的數據也不是直接寫入硬碟,而是寫入內存

但是Journaling日誌會消耗內存,所以可以在主庫上面關閉,在從庫上面啟動

可以單獨為Journaling日誌使用一塊固態硬碟

在插入時,可以通過驅動確保Journaling插入後再反饋,但是會非常影響性能。

logpath 選項指定日誌存儲地址

-vvvvv 選項(v越多,輸出越詳細)

db.runCommand({logrotare:1}) 開啟滾動日誌

(1)serverStatus

這里寫圖片描述

(2)top

(3)db.currentOp()

動態展示mongodb活動數據

佔用當前mongodb監聽埠往上1000號的埠

(1)mongomp

把資料庫內容導出成BSON文件,而mongorestore能讀取並還原這些文件

(2)mongorestore

把導出的BSON文件還原到資料庫

(3)備份原始數據文件

可以這么做,但是,操作之前需要進行鎖庫處理 db.runCommand({fsync:1,lock:true})

db.$cmd.sys.unlock.findOne() 請求解鎖操作,但是資料庫不會立刻解鎖,需要使用db.currentOp()驗證。

(1)修復

mongd --repair 修復所有資料庫

db.runCommand({repairDatabase:1}) 修復單個資料庫

修復就是根據Jourling文件讀取和重寫所有數據文件並重建各個索引

(2)壓緊

壓緊,會重寫數據文件,並重建集合的全部索引,需要停機或者在從庫上面運行,如果需要在主庫上面運行,需要添加force參數 保證加寫鎖。

(1)監控磁碟狀態

(2)為提升性能檢查索引和查詢

總的來說,掃描盡可能少的文檔。

保證沒有冗餘的索引,冗餘的索引會佔用磁碟空間、消耗更多的內存,在每次寫入時還需做更多工作

(3)添加內存

dataSize 數據大小 和 indexSize 索引大小,如果兩者的和大於內存,那麼將會影響性能。

storageSize超過dataSize 數據大小 兩倍以上,就會因磁碟碎片而影響性能,需要壓縮。

4. 【mongoDB】mongoDB 常用 js sql操作

1.從一張表中查詢符合條件的數據,復制到另一張臨時表

testSrcCollection為源表
testDestCollection_20211120為臨時表

UNVERIFIED:未激活
INEFFECTIVE:禁用
ACTIVE:激活
SUSPENDED:離職

MongoDB Shell Script操作備忘
https://blog.inhere.top/mongodb-shell-scriptcao-zuo-bei-wang/

為 mongo Shell 編寫腳本
https://www.docs4dev.com/docs/zh/mongodb/v3.6/reference/tutorial-write-scripts-for-the-mongo-shell.html

為MongoDB編寫Js維護腳本
https://zhangshenjia.com/it/mongodb-js

mongo Shell 編寫腳本
http://runoops.com/mongodb-shell-script.html

MongoDB 運行 js 腳本
https://chengchaos.github.io/2020/06/12/mongo-run-script.html

關於mongodb:mongo腳本中的文件寫入操作?
https://www.codenong.com/8971151

mongoDB 寫腳本
https://mongodb-documentation.readthedocs.io/en/latest/tutorial/write-scripts-for-the-mongo-shell.html#gsc.tab=0

5. 下面的sql語句對應的MongoDB語句該怎麼寫

創建表插入數據

create table a(序號 int,單位 varchar(10),工作 varchar(10),得分 int,打分 varchar(10)) insert into a values (1,'財務','gz1',100,'黎明')insert into a values (2,'財務','gz2',90,'黎明')insert into a values (3,'財務','gz3',80,'黎明')insert into a values (4,'銷售','gz4',70,'黎明')insert into a values (5,'銷售','gz5',60,'黎明')insert into a values (6,'銷售','gz6',50,'黎明')insert into a values (7,'人事','gz7',40,'黎明')insert into a values (8,'人事','gz8',30,'黎明')insert into a values (9,'人事','gz9',20,'黎明')insert into a values (10,'財務','gz1',88,'趙一')insert into a values (11,'財務','gz2',86,'趙一')insert into a values (12,'財務','gz3',78,'趙一')insert into a values (13,'銷售','gz4',90,'趙一')insert into a values (14,'銷售','gz5',64,'趙一')insert into a values (15,'銷售','gz6',85,'趙一')insert into a values (16,'人事','gz7',90,'趙一')insert into a values (17,'人事','gz8',43,'趙一')insert into a values (18,'人事','gz9',68,'趙一')

執行:

select 單位,工作,sum(case when 打分='黎明' then 得分 else 0 end) 黎明,sum(case when 打分='趙一' then 得分 else 0 end) 趙一from a group by 單位,工作

結果:

6. mongodb 怎麼執行sql

  1. 互動式 mongo shell

    mongo 127.0.0.1:27017

    use test

    db.users.findOne()

  2. mongo --eval 運行一段腳本

    mongo 127.0.0.1:27017/test --eval "printjson(db.users.findOne())"

  3. 在OS命令行下,運行一個js文件

    mongo127.0.0.1:27017/test userfindone.js

    userfindone.js 的內容:

    printjson(db.users.findOne());

  4. 在mongo shell 交互模式下,運行一個js文件

    mongo test

    load("/root/mongojs/userfindone.js")

    load() 參數中的文件路徑,既可以是相對路徑,也可以是絕對路徑。

    在mongo shell下查看當前工作路徑的方法: pwd( )

    當前工作路徑就是我們啟動mongo shell時,當前用戶所處的路徑。

    例如:

    [root@cgl-centos-dev mongojs]# pwd

    /root/mongojs

    [root@cgl-centos-dev mongojs]# mongo

    MongoDB shell version: 2.6.12

    connecting to: test

    > pwd()

    /root/mongojs

    >

  5. MongoDB 查詢數據的語法格式如下:

    db.collection.find(query, projection)

    query:可選,使用查詢操作符指定查詢條件

    projection:可選,使用投影操作符指定返回的鍵。查詢時返迴文檔中所有鍵值, 只需省略該參數即可(默認省略)。

  6. 如果你需要以易讀的方式來讀取數據,可以使用 pretty() 方法,語法格式如下:>db.col.find().pretty()

    pretty() 方法以格式化的方式來顯示所有文檔

    以下實例我們查詢了集合 col 中的數據:

    > db.col.find().pretty(){
    "_id" : ObjectId("56063f17ade2f21f36b03133"),
    "title" : "MongoDB 教程",
    "description" : "MongoDB 是一個 Nosql 資料庫",
    "by" : "菜鳥教程",
    "url" : "http://www.runoob.com",
    "tags" : [
    "mongodb",
    "database",
    "NoSQL"
    ],
    "likes" : 100}

    除了 find() 方法之外,還有一個 findOne() 方法,它只返回一個文檔。