精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

一口氣看完 43 個(gè)關(guān)于 ElasticSearch 的使用建議

開源
最近十年,Elasticsearch 已經(jīng)成為了最受歡迎的開源檢索引擎,并沉淀了大量的實(shí)踐案例及優(yōu)化總結(jié)。在本文中,我們盡可能全面地總結(jié)了 Elasticsearch 日常開發(fā)中的一些重要實(shí)踐&避坑指南,希望能為大家提供 Elasticsearch 使用上的一些借鑒點(diǎn),歡迎討論!

一、前言

本文分享了在工作中關(guān)于 ElasticSearch 的一些使用建議。和其他更偏向手冊化更注重結(jié)論的文章不同,本文將一定程度上闡述部分建議背后的原理及使用姿勢參考,避免流于表面,只知其然而不知其所以然。如有不當(dāng)?shù)牡胤剑瑲g迎指正!

二、查詢相關(guān)

充分利用緩存

  • 分片查詢緩存(Shard Request Cache)

ES 層面的緩存實(shí)現(xiàn),封裝在 IndicesRequestCache 類中。緩存的 Key 是整個(gè)客戶端請求,緩存內(nèi)容為單個(gè)分片的查詢結(jié)果。主要作用是對聚合的緩存,查詢結(jié)果中被緩存的內(nèi)容主要包括:Aggregations(聚合結(jié)果)、Hits.total、以及 Suggestions等。

并非所有的分片級查詢都會(huì)被緩存。只有客戶端查詢請求中 size=0 的情況下才會(huì)被緩存。其他不被緩存的條件還包括 Scroll、設(shè)置了 Profile 屬性,查詢類型不是 QUERY_THEN_FETCH,以及設(shè)置了 requestCache=false 等。另外一些存在不確定性的查詢例如:范圍查詢帶有 Now,由于它是毫秒級別的,緩存下來沒有意義,類似的還有在腳本查詢中使用了 Math.random() 等函數(shù)的查詢也不會(huì)進(jìn)行緩存。

當(dāng)有新的 Segment 寫入到分片后,緩存會(huì)失效,因?yàn)橹暗木彺娼Y(jié)果已經(jīng)無法代表整個(gè)分片的查詢結(jié)果。所以分片每次 Refresh 之后,緩存會(huì)被清除。

  • 節(jié)點(diǎn)查詢緩存/過濾器緩存(Node Query Cache /Filter Cache)

Lucene 層面的緩存實(shí)現(xiàn),封裝在 LRUQueryCache 類中,默認(rèn)開啟。緩存的是某個(gè) Filter 子查詢語句在一個(gè) Segment 上的查詢結(jié)果。

并非所有的 Filter 查詢都會(huì)被緩存。對于體積較小的 Segment 不會(huì)建立 Query Cache,因?yàn)樗麄兒芸鞎?huì)被合并。Segment 的 Doc 數(shù)量需要大于 10000,并且占整個(gè)分片的 3% 以上才會(huì)走 Cache 策略(參考:緩存)。

當(dāng) Segment 合并的時(shí)候,被刪除的 Segment 其關(guān)聯(lián) Cache 會(huì)失效。

01. 使用過濾器上下文(Filter)替代查詢上下文(Query)。

  • Filter不會(huì)進(jìn)行打分操作,而 Must 會(huì)。
  • Filter 查詢可以被緩存,從而提高查詢性能。

正例:

// 創(chuàng)建BoolQueryBuilder
    BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();


    // 構(gòu)建過濾器上下文
    boolQuery.filter(QueryBuilders.termQuery("field", "value"));

反例:

// 創(chuàng)建BoolQueryBuilder
    BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();


    // 構(gòu)建查詢上下文
    boolQuery.must(QueryBuilders.termQuery("field1", "value1"));

02. 只關(guān)注聚合結(jié)果而不關(guān)注文檔細(xì)節(jié)時(shí),Size 設(shè)置為 0 利用分片查詢緩存。

參考示例:

SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();


    // 添加聚合查詢
    sourceBuilder.aggregation(
        AggregationBuilders.terms("term_agg").field("field")
            .subAggregation(AggregationBuilders.sum("sum_agg").field("field"))
        );


    // 設(shè)置size為0,只返回聚合結(jié)果而不返回文檔
    sourceBuilder.size(0);

03. 日期范圍查詢使用絕對時(shí)間值。

日期字段上使用 Now,一般來說不會(huì)被緩存,因?yàn)槠ヅ涞降臅r(shí)間一直在變化。因此, 可以從業(yè)務(wù)的角度來考慮是否一定要用 Now,盡量使用絕對時(shí)間值,不需要解析相對時(shí)間表達(dá)式且利用 Query Cache 能夠提高查詢效率。例如時(shí)間范圍查詢中使用 Now/h,使用小時(shí)級別的單位,可以讓緩存在 1 小時(shí)內(nèi)都可能被訪問到。

正例:

SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();


        // 獲取當(dāng)前日期并格式化為絕對時(shí)間值
        LocalDateTime now = LocalDateTime.now();
        DateTimeFormatter formatter = DateTimeFormatter.ISO_DATE;
        String currentDate = now.format(formatter);


        // 創(chuàng)建日期范圍查詢
        sourceBuilder.query(QueryBuilders.rangeQuery("date_field")
                .gte("2022-01-01")
                .lte(currentDate));
反例:
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();


        // 創(chuàng)建日期范圍查詢,使用相對時(shí)間值
        sourceBuilder.query(QueryBuilders.rangeQuery("date_field")
                .gte("now-7d")
                .lte("now"));

聚合查詢

04.避免多層聚合嵌套查詢。

聚合查詢的中間結(jié)果和最終結(jié)果都會(huì)在內(nèi)存中進(jìn)行,嵌套過多,會(huì)導(dǎo)致內(nèi)存耗盡。

如:

SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();


        // 創(chuàng)建主要查詢
        sourceBuilder.query(QueryBuilders.matchAllQuery());


        // 創(chuàng)建第一層聚合
        TermsAggregationBuilder termAggBuilder1 = AggregationBuilders.terms("term_agg1").field("field_name1");


        // 創(chuàng)建第二層聚合
        TermsAggregationBuilder termAggBuilder2 = AggregationBuilders.terms("term_agg2").field("field_name2");
        termAggBuilder1.subAggregation(termAggBuilder2);


        // 創(chuàng)建第三層聚合
        TermsAggregationBuilder termAggBuilder3 = AggregationBuilders.terms("term_agg3").field("field_name3");
        termAggBuilder2.subAggregation(termAggBuilder3);


        sourceBuilder.aggregation(termAggBuilder1);

05. 嵌套查詢建議使用 Composite 聚合查詢方式。

對于常見的 Group by A,B,C 這種多維度 Groupby 查詢,嵌套聚合的性能很差,嵌套聚合被設(shè)計(jì)為在每個(gè)桶內(nèi)進(jìn)行指標(biāo)計(jì)算,對于平鋪的 Group by 來說有存在很多冗余計(jì)算,另外在 Meta 字段上的序列化反序列化代價(jià)也非常大,這類 Group by 替換為 Composite 可以將查詢速度提升 2 倍左右。

正例:

// 創(chuàng)建Composite Aggregation構(gòu)建器
        CompositeAggregationBuilder compositeAggregationBuilder = AggregationBuilders
                .composite("group_by_A_B_C")
                .sources(
                        AggregationBuilders.terms("group_by_A").field("fieldA.keyword"),
                        AggregationBuilders.terms("group_by_B").field("fieldB.keyword"),
                        AggregationBuilders.terms("group_by_C").field("fieldC.keyword")
                );


        // 創(chuàng)建查詢條件
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder()
                .query(QueryBuilders.matchAllQuery())
                .aggregation(compositeAggregationBuilder)
                .size(0);

反例:

// 創(chuàng)建Terms Aggregation構(gòu)建器,按照字段A分組
        TermsAggregationBuilder termsAggregationA = AggregationBuilders.terms("group_by_A").field("fieldA.keyword");


        // 在字段A的基礎(chǔ)上創(chuàng)建Terms Aggregation構(gòu)建器,按照字段B分組
        TermsAggregationBuilder termsAggregationB = AggregationBuilders.terms("group_by_B").field("fieldB.keyword");


        // 在字段B的基礎(chǔ)上創(chuàng)建Terms Aggregation構(gòu)建器,按照字段C分組
        TermsAggregationBuilder termsAggregationC = AggregationBuilders.terms("group_by_C").field("fieldC.keyword");


        // 將字段C的聚合添加到字段B的聚合中
        termsAggregationB.subAggregation(termsAggregationC);


        // 將字段B的聚合添加到字段A的聚合中
        termsAggregationA.subAggregation(termsAggregationB);


        // 創(chuàng)建查詢條件
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder()
                .query(QueryBuilders.matchAllQuery())
                .aggregation(termsAggregationA)
                .size(0);

06. 避免大聚合查詢。

聚合查詢的中間結(jié)果和最終結(jié)果都會(huì)在內(nèi)存中進(jìn)行,數(shù)據(jù)量太大會(huì)導(dǎo)致內(nèi)存耗盡。

07. 高基數(shù)場景嵌套聚合查詢建議使用 BFS 搜索。

聚合是在 ES 內(nèi)存完成的。當(dāng)一個(gè)聚合操作包含了嵌套的聚合操作時(shí),每個(gè)嵌套的聚合操作都會(huì)使用上一級聚合操作中構(gòu)建出的桶作為輸入,然后根據(jù)自己的聚合條件再進(jìn)行桶的進(jìn)一步分組。這樣對于每一層嵌套,都會(huì)再次動(dòng)態(tài)構(gòu)建一組新的聚合桶。在高基數(shù)場景,嵌套聚合操作會(huì)導(dǎo)致聚合桶數(shù)量隨著嵌套層數(shù)的增加指數(shù)級增長,最終結(jié)果就是占用 ES 大量內(nèi)存,從而導(dǎo)致 OOM 的情況發(fā)生。

默認(rèn)情況下,ES 使用 DFS(深度優(yōu)先)搜索。深度優(yōu)先先構(gòu)建完整的樹,然后修剪無用節(jié)點(diǎn)。BFS(廣度優(yōu)先)先執(zhí)行第一層聚合,再繼續(xù)下一層聚合之前會(huì)先做修剪。

在聚合查詢中,使用廣度優(yōu)先算法需要在每個(gè)桶級別上緩存文檔數(shù)據(jù),然后在剪枝階段后向子聚合重放這些文檔。因此,廣度優(yōu)先算法的內(nèi)存消耗取決于每個(gè)桶中的文檔數(shù)量。對于許多聚合查詢,每個(gè)桶中的文檔數(shù)量都非常大,聚合可能會(huì)有數(shù)千或數(shù)十萬個(gè)文檔。

但是,有大量桶但每個(gè)桶中文檔數(shù)量相對較少的情況下,使用廣度優(yōu)先算法能更加高效地利用內(nèi)存資源,而且可以讓我們構(gòu)建更加復(fù)雜的聚合查詢。雖然可能會(huì)產(chǎn)生大量的桶,但每個(gè)桶中只有相對較少的文檔,因此使用廣度優(yōu)先搜索算法可以更加節(jié)約內(nèi)存。

參考示例:

searchSourceBuilder.aggregation(
        AggregationBuilders.terms("brandIds")
                .collectMode(Aggregator.SubAggCollectionMode.BREADTH_FIRST)
                .field("brandId")
                .size(2000)
                .order(BucketOrder.key(true))
);

08.避免對 text 字段類型使用聚合查詢。

  • text 的 Fielddata 會(huì)加大對內(nèi)存的占用,如有需求使用,建議使用 Keyword。

09. 不建議使用 bucket_sort 進(jìn)行聚合深分頁查詢。

ES 的高 Cardinality 聚合查詢非常消耗內(nèi)存,超過百萬基數(shù)的聚合很容易導(dǎo)致節(jié)點(diǎn)內(nèi)存不夠用以至 OOM。

bucket_sort 使用桶排序算法,性能問題主要是由于它需要在內(nèi)存中緩存所有的文檔和聚合桶,然后才能進(jìn)行排序和分頁,隨著文檔數(shù)量增多和分頁深度增加,性能會(huì)逐漸變差,有深分頁問題。因?yàn)橥芭判蛐枰獙λ形臋n進(jìn)行整體排序,所以它的時(shí)間復(fù)雜度是 O(NlogN),其中 N 是文檔總數(shù)。

目前Elasticsearch支持聚合分頁(滾動(dòng)聚合)的目前只有復(fù)合聚合(Composite Aggregation)一種。滾動(dòng)的方式類似于SearchAfter。聚合時(shí)指定一個(gè)復(fù)合鍵,然后每個(gè)分片都按照這個(gè)復(fù)合鍵進(jìn)行排序和聚合,不需要在內(nèi)存中緩存所有文檔和桶,而是可以每次返回一頁的數(shù)據(jù)。

反例:使用 bucket_sort 深分頁 RT 達(dá)到 5000ms+

SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
  BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
  boolQuery.filter(QueryBuilders.termQuery(EsNewApplyDocumentFields.IS_DEL, 0));
  TermsAggregationBuilder termsAggregationBuilder = AggregationBuilders.terms("spuIdAgg").field("spuId").order(BucketOrder.key(false)).size(pageNum*pageSize);
  termsAggregationBuilder.subAggregation(new BucketSortPipelineAggregationBuilder("spuBucket",null).from((pageNum-1)*pageSize).size(pageSize));  searchSourceBuilder.query(boolQuery).aggregation(termsAggregationBuilder).size(0);

正例:使用 Composite Aggregation 優(yōu)化后深分頁查詢:423ms

SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        boolQuery.filter(QueryBuilders.termQuery(EsNewApplyDocumentFields.IS_DEL, 0));
        CompositeAggregationBuilder compositeBuilder = new CompositeAggregationBuilder(
                "spuIdAgg",
                Collections.singletonList(new TermsValuesSourceBuilder("spuId").field("spuId").order("desc"))
        ).aggregateAfter(ImmutableMap.of("spuId", "603030")).size(20);
        searchSourceBuilder.query(boolQuery).aggregation(compositeBuilder).aggregation(totalAgg).size(0);

分頁

10. 避免使用 from+size 方式。

ES 中深度翻頁排序的花費(fèi)會(huì)隨著分頁的深度而成倍增長,分頁搜索不會(huì)單獨(dú)“Cache”。每次分頁的請求都是一次重新搜索的過程,而不是從第一次搜索的結(jié)果中獲取。如果數(shù)據(jù)特別大對 CPU 和內(nèi)存的消耗會(huì)非常巨大甚至?xí)?dǎo)致 OOM。

11. 避免高實(shí)時(shí)性&大結(jié)果集場景使用 Scroll 方式。

基于快照的上下文。實(shí)時(shí)性高的業(yè)務(wù)場景不建議使用。大結(jié)果集場景將生成大量Scroll 上下文,可能導(dǎo)致內(nèi)存消耗過大,建議使用 SearcheAfter 方式。

思考:對于 Scroll 和 SearchAfter 的選用怎么看?兩者分別適用于哪種場景?SearchAfter 可以完全替代 Scroll 嗎?

Scroll 維護(hù)一份當(dāng)前索引段的快照,適用于非實(shí)時(shí)滾動(dòng)遍歷全量數(shù)據(jù)查詢,但大量Contexts 占用堆內(nèi)存的代價(jià)較高;7.10 引入的新特性 Search After + PIT,查詢本質(zhì)是利用前向頁面的一組排序之檢索匹配下一頁,從而保證數(shù)據(jù)一致性;8.10 官方文檔明確指出不再建議使用 Scroll API 進(jìn)行深分頁。如果分頁檢索超過 Top10000+ 推薦使用 PIT + Search After。

12. SearchAfter 分頁/Scroll ID/ 遍歷索引中的數(shù)據(jù)指定 Sort 字段要保證唯一性,否則會(huì)造成分頁/遍歷數(shù)據(jù)不完整或重復(fù)。

13. 建議指定業(yè)務(wù)字段排序,不要采用默認(rèn)打分排序。

ES 默認(rèn)使用“_score”字段按評分排序。如在使用 Scroll API 獲取數(shù)據(jù)時(shí),如果沒有特殊的排序需求,推薦使用"sort":"_doc"讓 ES 按索引順序返回命中文檔,可以節(jié)省排序開銷。原因如下:

  • 使用非文檔 ID 排序,會(huì)導(dǎo)致每次查詢 ES 需要在每個(gè)分片記住上次返回的最后一個(gè)文檔,然后下次查詢中會(huì)對之前已經(jīng)返回的文檔進(jìn)行忽略過濾,同時(shí)在協(xié)調(diào)節(jié)點(diǎn)進(jìn)行排序操作。文檔 ID 排序則不需要上述操作。
  • 對于文檔 ID 排序,ES 內(nèi)部進(jìn)行了特殊優(yōu)化,性能表現(xiàn)更優(yōu)。

14. Scroll 查詢確保顯式調(diào)用 clearScroll() 方法清除 Scroll ID。

否則會(huì)導(dǎo)致 ES 在過期時(shí)間前無法釋放 Scroll 結(jié)果集占用的內(nèi)存資源,同時(shí)也會(huì)占用默認(rèn) 3000 個(gè) Scroll 查詢的容量,導(dǎo)致 too many scroll ID 的查詢拒絕報(bào)錯(cuò),影響業(yè)務(wù)。

其他

15. 注意 Must 和 Should 同時(shí)出現(xiàn)在語句里的時(shí)候,Should 會(huì)失效;注意 Must 和 Should 同時(shí)出現(xiàn)在同一層級的 bool 查詢時(shí),Should 查詢會(huì)失效。

正例:

{"query":{ "bool":{
            "must":[
                {"bool":{
                        "must":[
                            {
                                "term":{
                                    "status.keyword":"1"
                           } }]}},
                {"bool":{
                        "should":[
                            {"term":{
                                    "tag.keyword":"1"
  } } ] }}]}}}

反例:

{"query":{
        "bool":{
            "must":[
                {
                    "term":{
                        "status.keyword":"1"
                    }}],
            "should":[
                {
                    "term":{
                        "tag.keyword":"1"
                    }
   }]}}}
16. 避免查詢 indexName-*。

因?yàn)?Elasticsearch 中的索引名稱是全局可見的,可以通過查詢所有索引的方式來枚舉某個(gè)集群中的所有索引名稱。可以通過在 Elasticsearch 配置文件中設(shè)置 action.destructive_requires_name 參數(shù)來禁止查詢 indexName-*。

17. 腳本使用 Stored 方式,避免使用 Inline 方式。

對于固定結(jié)構(gòu)的 Script,使用 Stored 方式,把腳本通過 Kibana 存入 ES 集群,降低重復(fù)編譯腳本帶來的性能損耗。

正例:

第1步:通過stored方式,建script模版:
POST _script/activity_discount_price
{
  "script":{
        "lang":"painless",
        "source":"doc.xxx.value * params.discount"
  }
}


第2步:調(diào)用script腳本模版:cal_activity_discount
GET index/_search
{
  "script_fields": {
    "discount_price": {
      "script": {
           "id": "activity_discount_price",
           "params":{
               "discount": 0.8
           }
}}}}

反例:

//直接inline方式,請求中傳入腳本:
GET index/_search
{
  "script_fields": {
    "activity_discount_price": {
      "script": {
           "source":"doc.xxx.value * 0.8"
      }
    }
  }
}

18. 避免使用 _all 字段。

_all 字段包含了所有的索引字段,如果沒有獲取原始文檔數(shù)據(jù)的需求,可通過設(shè)置Includes、Excludes 屬性來定義放入 _source 的字段。_all 默認(rèn)將寫入的字段拼接成一個(gè)大的字符串,并對該字段進(jìn)行分詞,用于支持整個(gè) Doc 的全文檢索,“_all”字段在查詢時(shí)占用更多的 CPU,同時(shí)占用更多的磁盤存儲(chǔ)空間,默認(rèn)為“false”,不建議開啟該字段和使用。

19. 建議用 Get 查詢替換 Search 查詢。

GET/MGET 直接根據(jù)文檔 ID 從正排索引中獲取內(nèi)容。Search 不指定_id,根據(jù)關(guān)鍵詞從倒排索引中獲取內(nèi)容。

20. 避免進(jìn)行多索引查詢。

反例:

GET /index1,index2,index3/_search
{
  "query": {
    "match_all": {}
  }
}

21. 避免單次召回大量數(shù)據(jù),建議使用 _source_includes 和 _source_excludes 參數(shù)來包含或排除字段。

大型文檔尤其有用,部分字段檢索可以節(jié)省網(wǎng)絡(luò)開銷。

參考示例:

// 創(chuàng)建SearchSourceBuilder,并設(shè)置查詢條件
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.query(QueryBuilders.matchAllQuery());


        // 設(shè)置要包含的字段
        String[] includes = {"field1", "field2"};
        sourceBuilder.fetchSource(includes, Strings.EMPTY_ARRAY);


        // 設(shè)置要排除的字段
        String[] excludes = {"field3"};
        sourceBuilder.fetchSource(Strings.EMPTY_ARRAY, excludes);

22. 避免使用 Wildcard 進(jìn)行中綴模糊查詢。

ES 官方文檔并不推薦使用 Wildcard 來進(jìn)行中綴模糊的查詢,原因在于 ES 內(nèi)部為了加速這種帶有通配符查詢,會(huì)將輸入的字符串 Pattern 構(gòu)建成一個(gè) DFA (Deterministic Finite Automaton),而帶有通配符的 Pattern 構(gòu)造出來的 DFA 可能會(huì)很復(fù)雜,開銷很大。

建議使用 ES 官方在 7.9 推出的一種專門用來解決模糊查詢慢的 Wildcard 字段類型。與 Text 字段相比,它不會(huì)將文本看作是標(biāo)點(diǎn)符號分割的單詞集合;與 Keyword 字段比,它在中綴搜索場景下具有無與倫比的查詢速度,且對輸入沒有大小限制,這是 Keyword 類型無法相比的。

23. 避免使用 Scripting。

Painless 腳本語言語法相對簡單,靈活度高,安全性高,性能高(相對于其他腳本,但是其性能比 DSL 要低)。不適用于非復(fù)雜業(yè)務(wù),一般 DSL 能解決大部分的問題,解決不了的用類似 Painless 等腳本語言。主要性能影響如下:單次查詢或更新耗時(shí)增加,腳本的執(zhí)行時(shí)間相比于其他查詢和更新操作可能會(huì)更長,因?yàn)樵趫?zhí)行腳本之前需要對其進(jìn)行詞法分析、語法分析和代碼編譯等預(yù)處理工作。

24. 避免使用腳本查詢(Script Query)計(jì)算動(dòng)態(tài)字段,建議在索引時(shí)計(jì)算并在文檔中添加該字段。

例如,我們有一個(gè)包含大量用戶信息的索引,我們需要查詢以"1234"開頭的所有用戶。運(yùn)行一個(gè)腳本查詢?nèi)?source":“doc[‘num’].value.startsWith(‘1234’)”。這個(gè)查詢非常耗費(fèi)資源,索引時(shí)考慮添加“num_prefix”的keyword字段,然后查詢"name_prefix":“1234”。

三、寫入相關(guān)

25. 避免代碼中或手工直接 Refresh 操作。

合理設(shè)置索引 Settings/Refresh_Interval 時(shí)間,通過系統(tǒng)完成 Refresh 動(dòng)作。

26. 避免單個(gè)文檔過大。

鑒于默認(rèn) http.max_content_length 設(shè)置為 100MB,Elasticsearch 將拒絕索引任何大于該值的文檔。

27. 寫入數(shù)據(jù)不指定 Doc_ID,讓 ES 自動(dòng)生成。

索引具有顯式 ID 的文檔時(shí) ES 在寫入過程中會(huì)多一步判斷的過程,即檢查具有相同ID 的文檔是否已經(jīng)存在于相同的分片中,隨著索引增長而變得更加昂貴。

28. 合理使用 Bulk API 批量寫。

大數(shù)據(jù)量寫入時(shí)可以使用 Bulk,但是請求響應(yīng)的耗時(shí)會(huì)增加,即使連接斷開,ES 集群內(nèi)部也仍然在執(zhí)行。高速大批量數(shù)據(jù)寫入時(shí),可能造成集群短時(shí)間內(nèi)響應(yīng)緩慢甚至假死的的情況。

  • 可以通過性能測試確定最佳數(shù)量,官方建議大約 5-15mb。
  • 超時(shí)時(shí)間需要足夠長,建議 60s 以上。
  • 寫入端盡量將數(shù)據(jù)輪詢打到不同節(jié)點(diǎn)上。

29. 腳本刷大量數(shù)據(jù),寫入前調(diào)大 Refresh Interval,不建議將副本分片為 0,待寫入完成后再調(diào)回來。

副本分片重新加入節(jié)點(diǎn)會(huì)觸發(fā)副分片恢復(fù) Recovery 流程,如果是大分片會(huì)影響集群性能。

四、索引創(chuàng)建

分片

30. 副本分片數(shù)大于等于 1。

高可用性保證。增加副本數(shù)可以一定程度上提高搜索性能;但會(huì)降低寫入性能,建議每個(gè)主分片對應(yīng) 1-2 個(gè)副本分片即可。

31. 官方建議單分片限制最大數(shù)據(jù)條數(shù)不超過 2^32 - 1。

32. 索引主分片數(shù)量不要設(shè)置過大。

ES 創(chuàng)建好索引后,一般情況下不再動(dòng)態(tài)調(diào)整主分片數(shù)量。

每個(gè)分片本質(zhì)上就是一個(gè) Lucene 索引,因此會(huì)消耗相應(yīng)的文件句柄、內(nèi)存和 CPU 資源。

ES 使用詞頻統(tǒng)計(jì)來計(jì)算相關(guān)性,當(dāng)然這些統(tǒng)計(jì)也會(huì)分配到各個(gè)分片上,如果在大量分片上只維護(hù)了很少的數(shù)據(jù),則將導(dǎo)致最終的文檔相關(guān)性較差。

一般來說,我們遵循一些原則:

  • 讀場景較多則可以設(shè)置少一點(diǎn),寫場景則可以設(shè)置多一些。
  • 控制每個(gè)分片占用的硬盤容量不超過ES的最大 JVM 的堆空間設(shè)置(32G),因此,如果索引的總?cè)萘吭?200G 左右,那分片大小在 7-8 個(gè)左右即可。
  • 考慮一下 Node 數(shù)量,一般一個(gè)節(jié)點(diǎn)對應(yīng)一臺物理機(jī),如果分片數(shù)遠(yuǎn)大于節(jié)點(diǎn)數(shù),則一個(gè)節(jié)點(diǎn)上存在多個(gè)分片,一旦該節(jié)點(diǎn)故障,即使保持了1個(gè)以上的副本,同樣有可能會(huì)導(dǎo)致數(shù)據(jù)丟失,集群無法恢復(fù)。所以, 一般都設(shè)置分片數(shù)不超過節(jié)點(diǎn)數(shù)的 3 倍。

33. 單個(gè)分片數(shù)據(jù)量不要超過 50GB。

單個(gè)索引的規(guī)模控制在 1TB 以內(nèi),單個(gè)分片大小控制在 30 ~ 50GB ,Docs 數(shù)控制在 10 億內(nèi),如果超過建議滾動(dòng)。

Mapping設(shè)計(jì)

34. 避免使用字段動(dòng)態(tài)映射功能,指定具體字段類型,子類型(若需要),分詞器(特別有場景需要)。

35. 對于不需要分詞的字符串字段,使用 Keyword 類型而不是 Text 類型。

36. ES 默認(rèn)字段個(gè)數(shù)最大 1000,建議不要超過 100。

單個(gè) Doc 在建立索引時(shí)的運(yùn)算復(fù)雜度,最大的因素不在于 Doc 的字節(jié)數(shù)或者說某個(gè)字段 Value 的長度,而是字段的數(shù)量。例如在滿負(fù)載的寫入壓力測試中,Mapping 相同的情況下,一個(gè)有 10 個(gè)字段,200 字節(jié)的 Doc, 通過增加某些字段 Value 的長度到 500 字節(jié),寫入 ES 時(shí)速度下降很少,而如果字段數(shù)增加到 20,即使整個(gè) Doc 字節(jié)數(shù)沒增加多少,寫入速度也會(huì)降低一倍。

37. 對于不索引字段,Index 屬性設(shè)置為 False。

在下面的例子中,Title 字段的 Index 屬性被設(shè)置為 False,表示該字段不會(huì)被包含在索引中。而 Content 字段的 Index 屬性默認(rèn)為 True,表示該字段會(huì)被包含在索引中。需要注意的是,即使 Index 屬性被設(shè)置為 False,該字段仍然會(huì)被保存在文檔中,可以被查詢和聚合。

參考示例:

{
  "mappings": {
    "properties": {
      "title": {
        "type": "text",
        "index": false
      },
      "content": {
        "type": "text"
      }
    }
  }
}

38. 避免使用 Nested 或 Parent/Child。

Nested Query慢,Parent/Child Query 更慢,針對 1 個(gè) Document,每一個(gè) Nested Field 都會(huì)生成一個(gè)獨(dú)立的 Document,這將使 Doc 數(shù)量劇增,影響查詢效率尤其是 JOIN 的效率。因此能在 Mapping 設(shè)計(jì)階段搞定的(大寬表設(shè)計(jì)或采用比較 Smart 的數(shù)據(jù)結(jié)構(gòu)),就不要用父子關(guān)系的 Mapping。如果一定要使用 Nested Fields,保證 Nested Fields字段不能過多,目前ES默認(rèn)限制是Index.mapping.nested_fields.limit=50。不建議使用 Nested,那有什么方式來解決 ES 無法 JOIN 的問題?主要有幾種實(shí)現(xiàn)方式:

  • 在文檔建模上盡可能在設(shè)計(jì)時(shí)將業(yè)務(wù)轉(zhuǎn)化有關(guān)聯(lián)關(guān)系的文檔形式,使用扁平的文檔模型。
  • 獨(dú)立索引存儲(chǔ),實(shí)際業(yè)務(wù)層分多次請求實(shí)現(xiàn)。
  • 通過寬表冗余存儲(chǔ)避免關(guān)聯(lián)。
  • 否則 Nested 和 Parent/Child 存儲(chǔ)對性能均有一定影響,由于 Nested 更新子文檔時(shí)需要 Reindex 整個(gè)文檔,所以對寫入性能影響較大,適用于 1 對 n(n 較小)場景;Parent/Child 存儲(chǔ)在相同 Type中,寫入相比 Nested性能高,用于 1 對 n(n 較大)場景,但比 Nested 查詢更慢,官網(wǎng)說是 5-10 倍左右。

39. 避免使用 Norms。

Norm 是索引評分因子,如果不用按評分對文檔進(jìn)行排序,設(shè)置為“False”。

參考示例:

"title": {"type": "string","norms": {"enabled": false}}

對于 Text 類型的字段而言,默認(rèn)開啟了 Norms,而 Keyword 類型的字段則默認(rèn)關(guān)閉了 Norms。

開啟 Norms 之后,每篇文檔的每個(gè)字段需要一個(gè)字節(jié)存儲(chǔ) Norms。對于 Text 類型的字段而言是默認(rèn)開啟 Norms 的,因此對于不需要評分的 Text 類型的字段,可以禁用 Norms。

40. 對不需要進(jìn)行聚合/排序的字段禁用列存 Doc_Values。

面向列的方式存儲(chǔ),主要用戶排序、聚合和訪問腳本中字段值等數(shù)據(jù)訪問場景。幾乎所有字段類型都支持 Doc_Values,值得注意的是,需要分析的字符串字段除外。默認(rèn)情況下,所有支持 Doc_Values 的字段都啟用了這個(gè)功能。如果確定不需要對字段進(jìn)行排序或聚合,或從腳本訪問字段值,則可以禁用此功能以減少冗余存儲(chǔ)成本。

Keyword和Numeric的選擇

Keyword 類型的主要缺點(diǎn)是在聚合的時(shí)候需要構(gòu)建全局序數(shù),而數(shù)值類型則不用。但低基數(shù)字段通常會(huì)命中大量結(jié)果集,例如性別,使用 Numeric 則會(huì)在構(gòu)建 Bitset 上產(chǎn)生很高的代價(jià)。

綜上所述,在類型選擇上可以參考下面的原則:

  • 在僅查詢的情況下,如果有 Range 查詢需求,使用 Numeric,否則使用 KeyWord。
  • 在僅聚合的情況下,如果明確字段是低基數(shù)的,使用 Keyword 配合 Execution_hint:map,其他情況使用 Numeric。
  • 剩下 Term 查詢+聚合的場景,需要綜合考慮 Numeric 類型 Term 查詢構(gòu)建 BitSet 和 Keyword 類型構(gòu)建全局序數(shù)哪個(gè)代價(jià)更大,需要看實(shí)際場景,但是目前所知的最壞情況下,構(gòu)建 Bitset 會(huì)導(dǎo)致 CPU 跑滿,構(gòu)建全局序數(shù)的主要問題是帶來的查詢延遲,也會(huì)給 JVM 帶來一些壓力。

41. 對于極少使用 Range 查詢的數(shù)字值,使用 Keyword 類型。

并非所有數(shù)值數(shù)據(jù)都應(yīng)映射為數(shù)值字段數(shù)據(jù)類型。Elasticsearch 為查詢優(yōu)化數(shù)字字段,例如 Integer or long。如果不需要范圍查找,對于 Term 查詢而言,Keyword 比 Integer 性能更好。

42. 對于有頻繁且較為固定的 Range 查詢字段,增加 Keyword 類型 Pre-Indexing字段。

如果對字段的大多數(shù)查詢在一個(gè)固定的范圍上運(yùn)行 Range 聚合,那么可以增加一個(gè) Keyword 類型的字段,通過將范圍“Pre-Indexing”到索引中并使用 Terms 聚合來加快聚合速度。

43. 對需要聚合查詢的高基數(shù) Keyword 字段啟用 Eager_Global_Ordinals。

參考:eager_global_ordinals

序號(Ordinals)用于在 Keyword 字段上運(yùn)行 Terms 聚合。序號用一個(gè)自增數(shù)值表示,ES 維護(hù)這個(gè)自增數(shù)字與實(shí)際值的映射關(guān)系,并為每一數(shù)值分配一個(gè) Bucket,映射關(guān)系是 Segment 級別的。

但是做聚合操作時(shí)往往需要結(jié)合多個(gè) Segment 的結(jié)果,而每個(gè) Segment 的 Ordinals 映射關(guān)系是不一致的,所以 ES 會(huì)在每個(gè)分片上創(chuàng)建全局序號(Global Ordinals)結(jié)構(gòu) ,一個(gè)全局統(tǒng)一的映射,維護(hù)全局的 Ordinal 與每個(gè) Segment 的 Ordinal 的映射關(guān)系。

默認(rèn)情況下,Global Ordinals 默認(rèn)是延時(shí)構(gòu)建,在第一次查詢?nèi)?Term Aggregation 使用到時(shí)才會(huì)構(gòu)建。因?yàn)?ES 不知道哪些字段將用于 Terms 聚合,哪些字段不會(huì)。對于基數(shù)大的字段,構(gòu)建成本較大。

啟用 eager_global_ordinals 后,Elasticsearch 會(huì)在分片構(gòu)建時(shí)預(yù)先計(jì)算出全局詞項(xiàng)表,以便在查詢時(shí)能夠更快地加載和使用。但啟用 eager_global_ordinals 后,每次執(zhí)行 Refresh 操作都會(huì)構(gòu)建 Global Ordinals,相當(dāng)于把搜索時(shí)候花費(fèi)的構(gòu)建成本轉(zhuǎn)移到寫入時(shí),所以會(huì)對寫入效率有一定的影響,可以配合增大索引的 Refresh Interval 來使用。

參考示例:

PUT index
{
    "mappings": {
        "type": { 
            "properties": {
                "foo": {
                    "type": "keyword",
                    "eager_global_ordinals" : true
                }
            }
        }
    }
}

五、總結(jié)

最近十年,Elasticsearch 已經(jīng)成為了最受歡迎的開源檢索引擎,并沉淀了大量的實(shí)踐案例及優(yōu)化總結(jié)。在本文中,我們盡可能全面地總結(jié)了 Elasticsearch 日常開發(fā)中的一些重要實(shí)踐&避坑指南,希望能為大家提供 Elasticsearch 使用上的一些借鑒點(diǎn),歡迎討論!

參考文章:

1.《Elasticsearch 源碼解析與優(yōu)化實(shí)戰(zhàn)》

2.《Elasticsearch權(quán)威指南》

3.https://www.easyice.cn/archives/367

4.https://www.elastic.co/guide/en/elasticsearch/guide/current/filter-caching.html#_independent_query_caching

5.https://www.elastic.co/guide/cn/elasticsearch/guide/current/_preventing_combinatorial_explosions.html

6.https://www.elastic.co/guide/en/elasticsearch/reference/current/eager-global-ordinals.html

責(zé)任編輯:武曉燕 來源: 得物技術(shù)
相關(guān)推薦

2021-06-08 22:43:07

IPC方式Qt

2021-03-29 12:22:25

微信iOS蘋果

2020-03-31 08:12:25

Kafka架構(gòu)數(shù)據(jù)庫

2020-10-21 06:39:21

CPU寄存器架構(gòu)

2024-01-29 00:29:49

通信技術(shù)行業(yè)

2021-12-06 08:30:49

SpringSpring Bean面試題

2025-05-14 01:55:00

FCMCPAI

2020-10-22 12:30:33

MySQL

2020-09-24 09:08:04

分布式系統(tǒng)架構(gòu)

2020-04-14 13:32:56

@Transacti失效場景

2021-03-01 18:52:39

工具在線瀏覽器

2024-04-26 09:40:10

項(xiàng)目精度丟失javascrip

2022-05-24 11:50:46

延時(shí)消息分布式

2021-05-18 09:03:16

Gomapslice

2020-07-08 07:45:44

OAuth2.0授權(quán)

2022-08-14 15:40:55

表情DIY

2024-03-26 09:42:27

分片算法應(yīng)用

2021-01-04 11:23:21

手機(jī)無線電通訊

2024-03-28 12:52:00

AI模型

2010-03-20 21:51:27

pwn2OwnMac OS X漏洞
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號

日本精品一区二区三区高清 久久| 欧美日韩免费高清一区色橹橹| 91久久久一线二线三线品牌| 欧美大片xxxx| 视频一区中文字幕精品| 亚洲妇女屁股眼交7| 成人激情综合网| 欧美成人aaa片一区国产精品| 综合欧美亚洲| 欧美性猛交视频| 亚洲国产精品一区二区第一页| 一级黄在线观看| 综合一区av| 日韩经典第一页| 日韩免费高清在线| 欧美一区二区三区| 精彩视频一区二区三区| 欧美国产乱视频| aa片在线观看视频在线播放| 88xx成人网| 亚洲国产成人高清精品| 蜜桃av久久久亚洲精品| 国模私拍一区二区| 亚洲高清影视| 亚洲精品国产综合区久久久久久久| 国产真实乱子伦| 黄色免费在线观看网站| 波多野结衣91| 91精品久久久久久久久久另类 | 国产女人水真多18毛片18精品| 国产性猛交╳xxx乱大交| 93在线视频精品免费观看| 亚洲精品美女在线| 97中文字幕在线观看| 国产一区影院| 91久久精品日日躁夜夜躁欧美| 成人性生活视频免费看| av在线下载| 中文字幕一区二区三区在线不卡| 欧美日韩国产综合视频在线| 性生活免费网站| 加勒比av一区二区| 国产欧美精品在线播放| 中文字幕欧美人妻精品| 久久久777| 欧美一级视频一区二区| 国产午夜激情视频| 欧美涩涩网站| 欧美极度另类性三渗透| 欧美日韩人妻精品一区二区三区| 婷婷综合在线| 精品国产一区二区三区四区在线观看| 国产毛片欧美毛片久久久| 国产精品一区高清| 国产亚洲精品一区二区| 自拍偷拍视频亚洲| 少妇精品久久久一区二区三区| 亚洲国产精品成人一区二区| 性色av蜜臀av浪潮av老女人| 粉嫩久久久久久久极品| 精品国免费一区二区三区| jjzz黄色片| 第四色在线一区二区| 精品国产91久久久久久久妲己| 亚洲熟女一区二区三区| 国语一区二区三区| 日韩av影视在线| 女人被狂躁c到高潮| 亚洲都市激情| 宅男66日本亚洲欧美视频| www.黄色在线| 91精品国产91久久久久久黑人| 久热精品视频在线| 国产精品成人免费一区二区视频| 亚洲激情视频| 国产99在线|中文| 中文字幕在线观看你懂的| 久久99九九99精品| 91一区二区三区| 四虎永久在线精品免费网址| 99国产精品99久久久久久| 日韩国产一区久久| 老司机精品视频在线观看6| 亚洲精品成人精品456| 国产美女主播在线| 欧美极品影院| 91精品国产麻豆| 久久人人爽人人人人片| 精品一区二区三区在线| 美日韩精品免费观看视频| 日韩乱码一区二区| 日本伊人精品一区二区三区观看方式| 成人免费视频网址| 婷婷色在线视频| 国产精品乱子久久久久| 人人妻人人做人人爽| 网友自拍亚洲| 日韩欧美激情在线| 中文字幕国产综合| 欧美黄免费看| 久久久久久成人精品| 色老头一区二区| 国产福利一区二区三区| 欧美不卡三区| 最爽无遮挡行房视频在线| 欧美午夜精品久久久久久人妖 | 国产精品一区二区久久不卡| 精品在线一区| 国产在线69| 欧美视频在线看| 毛毛毛毛毛毛毛片123| 一区二区美女| 欧美精品18videos性欧| 中文字幕有码视频| 97国产精品videossex| 国产奶头好大揉着好爽视频| 国产精品专区免费| 日韩欧美国产系列| www.xx日本| 美女被久久久| 国产欧美在线一区二区| 国产一二区在线观看| 一本高清dvd不卡在线观看| 日本黄色大片在线观看| 欧美电影三区| 国产极品精品在线观看| 性xxxx搡xxxxx搡欧美| 亚洲三级小视频| 黄色片视频在线| 嫩草影视亚洲| 97av视频在线| 欧美特级特黄aaaaaa在线看| 一区二区三区在线视频观看| 亚欧美在线观看| 国产一区二区精品久| 午夜欧美不卡精品aaaaa| www.五月激情| 亚洲人吸女人奶水| 欧美wwwwwww| 欧美午夜精彩| 国产成人一区二区三区电影| 色窝窝无码一区二区三区| 亚洲国产精品一区二区www在线| 北条麻妃亚洲一区| 在线看片不卡| 91观看网站| bt在线麻豆视频| 91精选在线观看| 亚洲精品卡一卡二| 激情国产一区二区| 异国色恋浪漫潭| 国产va免费精品观看精品| 久久九九免费视频| av高清一区二区| 亚洲伦理在线精品| 下面一进一出好爽视频| 你懂的成人av| 国产精品日韩一区二区| 蜜桃视频在线观看播放| 亚洲精品美女在线观看播放| 你懂的国产在线| 久久久高清一区二区三区| www.国产区| 精品美女视频| 91精品国产综合久久久久久久久| 成人免费视屏| 亚洲成人中文字幕| 天天干在线播放| 欧美国产日本韩| 中文字幕丰满乱码| 欧美精品日韩| 久久久久se| www.一区| 成人97在线观看视频| 亚洲AV无码精品色毛片浪潮| 午夜精品久久久久久久久久 | 国产精品久久久久7777按摩| 天堂av手机在线| 亚洲激情专区| 日韩国产在线一区| 欧美三级一区| 日本久久久久久| 国产丝袜在线| 精品一区二区三区四区| 在线视频1卡二卡三卡| 亚洲精品日韩一| 无遮挡aaaaa大片免费看| 久久国产夜色精品鲁鲁99| 高清无码视频直接看| 综合亚洲自拍| 亚洲r级在线观看| 黑森林国产精品av| 国产亚洲一级高清| 亚洲AV午夜精品| 欧美性猛交99久久久久99按摩| 91制片厂在线| 99re这里只有精品6| 天堂在线中文在线| 在线亚洲观看| 国产人妻互换一区二区| 亚洲制服一区| ts人妖另类在线| 国产精品亚洲d| 久久免费精品视频| 米奇777四色精品人人爽| 日韩精品欧美国产精品忘忧草| 91美女精品网站| 日韩欧美一区二区三区| 激情综合五月网| 中文字幕 久热精品 视频在线| 91丨porny丨对白| 国模大尺度一区二区三区| 亚欧无线一线二线三线区别| 亚洲精品二区三区| 日本一区二区三区免费观看| xxxx日韩| 亚洲qvod图片区电影| 欧美日韩国产网站| 97人人爽人人喊人人模波多 | 国产成a人亚洲精v品无码| 色哟哟一区二区在线观看| 久久久久久久福利| 亚洲图片激情小说| 人与嘼交av免费| 久久综合久久综合九色| 亚洲天堂美女视频| 国产盗摄视频一区二区三区| 奇米影视四色在线| 日韩成人精品在线| 干日本少妇首页| 在线亚洲国产精品网站| 久久人人爽人人爽人人av| 中国精品18videos性欧美| 亚洲综合av一区| 欧美日韩国产在线观看网站| 欧洲久久久久久| 欧美网色网址| 久久av二区| 日韩一级电影| 九九九九九九精品| 秋霞蜜臀av久久电影网免费| 国精产品99永久一区一区| 国产成人一二片| 国语精品中文字幕| 农村少妇一区二区三区四区五区| 国产一区二区三区奇米久涩| 久久a爱视频| 黑人另类av| 日本亚洲不卡| 欧美精品一区三区在线观看| 一区二区三区韩国免费中文网站| 精品亚洲欧美日韩| 香蕉精品久久| 日本精品视频一区| 成人a'v在线播放| 亚洲mv在线看| 婷婷综合激情| 激情五月婷婷六月| 国产精品毛片一区二区三区| 黄色动漫网站入口| 日韩电影网1区2区| 高清av免费看| 国产精品正在播放| 丝袜熟女一区二区三区| 久久综合给合久久狠狠狠97色69| 天堂久久精品忘忧草| 国产精品视频第一区| 黄色香蕉视频在线观看| 亚洲一区二区三区在线| 在线观看国产亚洲| 欧美在线视频不卡| av在线资源观看| 亚洲精品国产综合久久| 福利在线观看| 久久精品最新地址| 成年女人在线看片| 国产精品99久久久久久久久久久久| 福利视频亚洲| 51国产成人精品午夜福中文下载| 好吊妞国产欧美日韩免费观看网站 | 在线电影中文日韩| 超碰个人在线| 欧美中文字幕在线播放| 四虎影视国产精品| 国产精品一区二区在线观看| 精品国产一级毛片| 日本精品福利视频| 老妇喷水一区二区三区| 国产高清av片| 91免费在线播放| 午夜精品福利在线视频| 天天综合色天天综合色h| 中文字幕在线观看你懂的| 亚洲国产精品久久久久秋霞蜜臀| yiren22亚洲综合伊人22| 欧美成人自拍视频| 人人鲁人人莫人人爱精品| 亚洲已满18点击进入在线看片| 色哟哟精品丝袜一区二区| 一区二区三区四区不卡| 国产日韩一区二区三区在线| 99精品视频国产| 久久久蜜桃精品| 免费在线视频观看| 欧美三级韩国三级日本三斤| 人人妻人人澡人人爽人人欧美一区 | 亚洲少妇一区二区| 欧美激情一区在线观看| 香蕉视频一区二区| 制服丝袜国产精品| 男女av在线| 欧美精品video| 成人97精品毛片免费看| 欧美高清视频一区| 在线观看日韩av电影| 男人午夜视频在线观看| 国产亚洲制服色| 天堂网一区二区三区| 91精品国产高清一区二区三区蜜臀| 黄色国产在线| 91国产视频在线播放| 在线综合色站| 永久免费在线看片视频| 免费在线观看视频一区| 一本加勒比北条麻妃| 亚洲va欧美va人人爽午夜| 国产麻豆免费观看| 日韩中文字幕在线精品| 午夜av成人| 欧美一区二区视频17c| 亚洲免费播放| 国产精品一区二区人妻喷水| 一区二区成人在线观看| 99久久精品国产色欲| 久久久91精品| 国产精品原创视频| 亚洲欧美日韩国产yyy| 日韩和欧美的一区| 欧美18—19性高清hd4k| 91成人国产精品| 黄色片在线免费看| 国产成人avxxxxx在线看| 亚洲美女久久| 国产免费成人在线| 91老师国产黑色丝袜在线| 欧美啪啪小视频| 国产视频一区在线| 欧美xxxxxx| 日韩精品伦理第一区| 日本麻豆一区二区三区视频| 国产又黄又粗的视频| 在线亚洲欧美专区二区| 国产精品一区二区婷婷| 国产精品久久久久秋霞鲁丝| 日韩精品网站| 91看片破解版| 一区二区三区在线观看欧美| 黄色av一区二区三区| 97激碰免费视频| 久草在线成人| 成 人 黄 色 小说网站 s色| 中文字幕永久在线不卡| av中文字幕第一页| 91成品人片a无限观看| 欧美激情在线免费| 欧美美女一级片| 一区二区三区日韩精品视频| 人妻丰满熟妇av无码区hd| 欧美一级大胆视频| 成人在线免费视频观看| 亚洲一区二区福利视频| 亚洲综合精品久久| 亚洲日本香蕉视频| 国产精品欧美激情在线播放| 91成人精品| 成人在线电影网站| 91国在线观看| 91在线中字| 久久久www免费人成黑人精品| 日韩电影在线观看网站| 成年人av电影| 亚洲欧美一区二区三区久久| 日韩免费在线电影| 日本人体一区二区| 国产欧美日韩视频在线观看| 精品人妻午夜一区二区三区四区 | 中文字幕xxxx| 另类视频在线观看| 欧美综合自拍| 99九九99九九九99九他书对| 精品二区三区线观看| 在线观看免费版| 国产亚洲一区在线播放| 免费观看日韩av| 日韩av在线播| 中文字幕国产精品| 欧美美女在线直播| 亚洲在线观看网站| 色婷婷综合久久久中文一区二区| 国产激情视频在线|