Elastic Stack-Elasticsearch使用介紹(五)

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"
                ]
            }
        ]
    }
}
View Code

 看到結果咱們就能夠知道咱們的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,歡迎你們關注我公衆號!

 

相關文章
相關標籤/搜索