1、前言html
前4篇將Elasticsearch用法的API和原理方面東西介紹了一下,相信你們對Elasticsearch有了必定的認知,接下咱們主要從索引的創建到後期的一些優化作一些介紹;node
2、Mapping構建數據庫
以前介紹過Index就如同咱們的數據庫database,type至關於咱們的表,而Mapping就是構建這些字段和索引關係的橋樑。數據庫構建的時候咱們要遵照三範式,那Mapping構建的時候咱們要考慮那些因素?我認爲要有如下幾方面的考慮:segmentfault
1.字段是什麼類型;緩存
對字段的類型作過介紹,考慮這個時候和數據庫字段設置考慮問題基本同樣;多線程
2.是否須要被檢索,也就是是否須要分詞;app
不須要檢索的字段:index設置爲false;不須要檢索的字符類型直接設置成keyword類型;elasticsearch
須要檢索的字段,能夠經過index_options設定須要的存儲分詞的粒度,主要有如下四種參數docs 、 freqs 、 position 、 offsets,根據須要自行設定;ide
3.是否須要排序和聚合;工具
不須要排序或者聚合分析功能:doc_values設置爲 false,fielddata設置爲 false;
若是一個字段不須要檢索、排序、聚合分析,則enabled設置爲false;
4.是否須要另外的存儲;
經過store 設定 true,便可存儲該字段的原始內容,這裏這個舉個例子
以上就是咱們創建Mapping時候須要考慮一些東西,接下來咱們還有另一個問題,數據庫中表與表之間是有關聯關係的,這個在Elasticsearch中是如何體現的?
在Elasticsearch中有兩種方式能夠去實現關聯關係,
1.Nested Object(嵌套對象)
舉個例子:
這個時候user字段會被映射成爲object類型,這個時候JSON文檔會被處理成爲:
當咱們查詢的時候,就會意外出現的結果;
結果:
Elasticsearch針對這種狀況提供Nested Object(嵌套對象)這個解決方案,
增長這一個步驟而後再按照上面步驟操做,就獲得咱們想要的結果;
當使用Nested Object內部是使用嵌套文檔,當搜索first name爲Alice和last name爲White的時候就查詢不到;
2.join
join數據類型是在同一個索引經過Parent和Child去指定父文檔和子文檔,而後造成1對多或者1對1的關係,舉個例子:
我這個是5.0以上的版本,不是6.0的版本,這個我仍是忘記說,你們注意下版本問題,我大概說下這個意思就是隻指定my_join_field字段question的父級爲answer;
接下來咱們再加入2條父級文檔:
接下來在加入2條子文檔:
這裏須要注意的問題是路由必需要指定,父級文檔必須和本身文檔在同一個分片上,另外就是指定join的文檔和父id;
這個時候咱們查看下咱們造成的文檔:
{ "took": 13, "timed_out": false, "_shards": { "total": 5, "successful": 5, "skipped": 0, "failed": 0 }, "hits": { "total": 4, "max_score": null, "hits": [ { "_index": "my_index", "_type": "doc", "_id": "1", "_score": null, "_source": { "text": "This is a question", "my_join_field": { "name": "question" } }, "sort": [ "1" ] }, { "_index": "my_index", "_type": "doc", "_id": "2", "_score": null, "_source": { "text": "This is a another question", "my_join_field": { "name": "question" } }, "sort": [ "2" ] }, { "_index": "my_index", "_type": "doc", "_id": "3", "_score": null, "_routing": "1", "_source": { "text": "This is an answer", "my_join_field": { "name": "answer", "parent": "1" } }, "sort": [ "3" ] }, { "_index": "my_index", "_type": "doc", "_id": "4", "_score": null, "_routing": "1", "_source": { "text": "This is another answer", "my_join_field": { "name": "answer", "parent": "1" } }, "sort": [ "4" ] } ] } }
看到結果咱們就能夠知道咱們的1對多關係已經創建起來了,接下來咱們按照父id來查詢父id爲1的文檔:
這個地方還要提醒下,也是可使用get的,只是使用神器的時候這樣比較方便;
結果以下:
還可使用has_child 返回包含某子文檔的父文檔,has_parent 返回包含某父文檔的子文檔這些就不寫例子本身探索一下吧;
接下來作個對比:
注意:Mapping字段不要設置太多;
3、部分優化的意見
elasticsearch.yml中建議設定的參數:
以前集羣搭建的時候你們確定設置一些參數,另外上面你的介紹也設置了一些參數,咱們也具體來講下在上生產環境以前到底要設置那些參數:
1.cluster.name集羣名稱;
2.node.name節點名稱;
3.node.master是不是主節點;
4.node.data是否存放數據,主節點不建議存放數據;
5.discovery.zen.ping.unicast.hosts設置集羣的其餘節點;
6.network.host IP;
7.path.data and path.logs 存放記錄和日誌的目錄,默認是在Elasticsearch目錄下;
8.discovery.zen.minimum_master_nodes 集羣掛掉之後選舉主的個數;
JVM設置:
1.將最小堆大小(Xms)和最大堆大小(Xmx)設置爲彼此相等,防止垃圾回收過於頻繁;
2.將Xmx設置爲不超過物理RAM的50%,以確保有足夠的物理RAM用於內核文件系統緩存;
3.不要超過32GB,這是JVM優化的建議;
分片的設置:
建議閱讀這篇文章;
讀寫優化:
寫入的優化,這個參考下Elastic Stack-Elasticsearch使用介紹(三)這篇文章,這篇文章我介紹寫入時候的一些步驟,咱們優化的方向就是從這3個方向:
固然要貫徹多線程、批量寫入這個不能變得方針,針對refresh、translog、flush這3個方面作優化:
1.refresh
每refresh一次都會生成一個segment,若是refresh頻率太高,可能會照成segment包含的文檔數是不多,生成不少的segment;
調整方向
增大refresh_interval,下降實時性,默認是1s,設置爲-1直接禁止自動refresh;
增大緩存區的大小,參數爲indices.memory.index_buffer_size(靜態參數,在elasticsearch.yml中設定,該參數設置後必須重啓節點),默認爲10%;
2.translog
目標是下降translog寫磁盤的頻率,從而提升效率,可是這樣就會有掉丟數據的風險;
調整方向
index.translog.durabiliy設置爲asyn,index.translog.sync_interval設置寫入時間的間隔,單位是秒,好比10s,那麼translog會改成每10s寫一次磁盤,這個時候若是宕機就會丟失數據;
index.translog.flush_threshold_size 默認爲512MB,超過該大小時會觸發一次flush;
3.合理設置節點和分片的個數,經過設置index.routing.allocation.total_shards_per_node 限定每一個索引在每一個節點上可分配的總主副分片的個數;
讀取的優化:
1.合理設置分片數
經過測試一個分片性能,而後根據業務進行計算,設置合理的分片個數;怎麼測試一個分片的性能?首先搭建與生產同樣的環境,接下來設定一個單分片無副本的索引,而後進行寫入數據測試 和查詢數據,而後根據提供的監控指標進行監控壓力測試的狀況,這部分監控內容下一章進行講解;壓測工具可使用esrally,參考下這篇文章;
2.優化查詢語句
儘可能使用Filter上下文,減小算分的場景,因爲Filter有緩存機制,能夠提高查詢性能;
4、結束
接下來會開始說一說監控的問題,歡迎你們加羣438836709,歡迎你們關注我公衆號!