一例Query Cache引起的性能問題分析

原載于Elastic中文社區(qū): https://elasticsearch.cn/article/304
本文是針對(duì)社區(qū)問題question#2484 的分析和總結(jié)阱佛。

問題概述

一個(gè)線上集群惶楼,執(zhí)行的Query DSL都是一樣的狰腌,只是參數(shù)不同您宪。 統(tǒng)計(jì)數(shù)據(jù)顯示98-99%的查詢響應(yīng)速度都很快痕惋,只需要4 -6ms号俐, 但有1%左右的查詢響應(yīng)時(shí)間在100ms - 200ms。 集群硬件配置較高救欧,使用的SSD衰粹,系統(tǒng)可用內(nèi)存遠(yuǎn)高于索引文件大小總和,并且線上已經(jīng)運(yùn)行有一段時(shí)間笆怠,數(shù)據(jù)應(yīng)該已經(jīng)充分預(yù)熱铝耻。


診斷過程及結(jié)論

比較巧的是,問題提出者剛好是我們自家公司的開發(fā)者蹬刷,因此內(nèi)部聯(lián)系溝通了下田篇,為問題的快速診斷提供了不少便利。

首先用公司的監(jiān)控系統(tǒng)排查了一遍集群所有關(guān)鍵數(shù)據(jù)箍铭,未發(fā)現(xiàn)任何可能引起查詢耗時(shí)高的性能瓶頸問題。 因此初步懷疑就是有查詢本身比較慢椎镣。 幸好公司有應(yīng)用埋點(diǎn)系統(tǒng)和日志系統(tǒng)诈火,因此很方便的拿到了應(yīng)用端發(fā)出的一些慢查詢樣例,包括請(qǐng)求體以及耗時(shí)状答。

以下是埋點(diǎn)系統(tǒng)里記錄的一個(gè)耗時(shí)150ms的查詢 (隱去了敏感信息冷守,去掉了非關(guān)鍵部分):

POST /xxxindex/xxxdb/_search?routing=Mxxxxxxx
{
  "from": 0,
  "size": 100,
  "query": {
    "bool": {
      "filter": [
        {
          "bool": {
            "must": [
              {
                "bool": {
                  "must": [
                    {
                      "bool": {
                        "should": [
                          {
                            "match_phrase": {
                              "ord_orders_uid": {
                                "query": "Mxxxxxxx",
                                "slop": 0,
                                "boost": 1
                              }
                            }
                          }
                        ],
                        "disable_coord": false,
                        "adjust_pure_negative": true,
                        "boost": 1
                      }
                    },
                    {
                      "range": {
                        "ord_orders_orderdate": {
                          "from": "1405032032",
                          "to":   "1504014193",
                          "include_lower": true,
                          "include_upper": true,
                          "boost": 1
                        }
                      }
                    },
                    {
                      "term": {
                        "ord_orders_ispackageorder": {
                          "value": 0,
                          "boost": 1
                        }
                      }
                    },
                    {
                      "bool": {
                        "must_not": [
                          {
                            "exists": {
                              "field": "ord_hideorder_orderid",
                              "boost": 1
                            }
                          }
                        ],
                        "disable_coord": false,
                        "adjust_pure_negative": true,
                        "boost": 1
                      }
                    }
                  ],
                  "disable_coord": false,
                  "adjust_pure_negative": true,
                  "boost": 1
                }
              }
            ],
            "disable_coord": false,
            "adjust_pure_negative": true,
            "boost": 1
          }
        }
      ],
      "disable_coord": false,
      "adjust_pure_negative": true,
      "boost": 1
    }
  }
}

拿到查詢后,自己手動(dòng)執(zhí)行了一下惊科,0 hits拍摇,耗時(shí)1ms。 心里明白馆截,命中了Query Cache充活,所以才會(huì)這么快。

于是用clear api清掉Query Cache蜡娶,然后再執(zhí)行幾次混卵,有以下發(fā)現(xiàn):

  • 頭兩次查詢耗時(shí)38ms左右。 這是因?yàn)闆]有cache窖张,需要訪問倒排索引幕随,耗時(shí)符合預(yù)期。 之所以兩次同樣耗時(shí)宿接,是因?yàn)樗饕?個(gè)復(fù)制片赘淮,兩次查詢分別分配到主和副片上辕录。
  • 接下來兩次查詢耗時(shí)150ms左右。 這里要打一個(gè)大大的問號(hào)梢卸?走诞??
  • 之后不管再查詢多少次低剔, 耗時(shí)全部是1ms速梗,因?yàn)橛珠_始命中Cache。

至此襟齿,大致明白姻锁,埋點(diǎn)系統(tǒng)里記錄到的高耗時(shí)查詢,是步驟2的兩次操作猜欺。 什么操作耗時(shí)這么久呢位隶? 根據(jù)經(jīng)驗(yàn),我判斷主要是用于為range filter生成緩存开皿,也就生成生成文檔列表的bitmap涧黄,然后存放到Query Cache里。

這個(gè)集群版本是5.1.1赋荆, 而我記得ES某個(gè)5版本開始笋妥,去掉了對(duì)term filter的cache,理由是term filter速度足夠快窄潭,緩存term filter往往得不償失春宣。 查了官方release notes,證實(shí)這個(gè)改變正好是從5.1.1開始的#21566嫉你,因此上面查詢里的term filters被排除掉月帝,注意力集中到了查詢里唯一的一個(gè)range filter。

單獨(dú)執(zhí)行了一下這個(gè)range filter幽污,match的文檔是千萬數(shù)量級(jí)的嚷辅。 詢問用戶,為何這個(gè)range filter會(huì)hit這么多文檔距误,得知用戶主要就是查詢從當(dāng)前時(shí)間開始至過去1年的數(shù)據(jù)簸搞,類似于做了一個(gè)now-1y TO now這樣的過濾。至此初步得出結(jié)論准潭,因?yàn)檫@個(gè)range filter匹配的文檔太多了攘乒,在Query Cache里為這個(gè)filter構(gòu)建bitmap耗時(shí)會(huì)有些高,應(yīng)該就是它帶來了那額外的100多個(gè)ms惋鹅。

但是還有一個(gè)待解釋的問題则酝,這種高耗時(shí)查詢比例為何這么高? 再仔細(xì)想想也就明白了:因?yàn)檫@個(gè)集群的搜索并發(fā)量還是有點(diǎn)高,300 -400/s的樣子沽讹,加上時(shí)間字段的精度是秒般卑,所以,在某一秒剛開始的時(shí)候爽雄,頭2次查詢因?yàn)闆]有cache蝠检,耗時(shí)可能在38ms左右,之后會(huì)有2次查詢因?yàn)樾枰彺鎟ange filter挚瘟,耗時(shí)會(huì)增加到150-200ms的樣子叹谁,之后這1秒里剩余的查詢都會(huì)命中cache,全部是幾個(gè)ms乘盖, 直到下一秒開始焰檩, 周而復(fù)始。 因?yàn)槊棵腌姸籍a(chǎn)生2個(gè)這樣需要構(gòu)建緩存的查詢订框,耗時(shí)較高析苫,對(duì)比每秒幾百次的查詢量,換算成百分比就有點(diǎn)高了穿扳。

那么怎么解決這個(gè)問題衩侥? 對(duì)于大量含有從now-xxx TO now這樣的range查詢,實(shí)際上官方的文檔有對(duì)應(yīng)的加速技巧介紹:tune-for-search-speed.html#_search_rounded_dates 矛物。也就是說茫死,將查詢時(shí)間的上下限r(nóng)ound到整分鐘,或者整小時(shí)履羞,讓range filter可以緩存得更久峦萎,避免出現(xiàn)這種過于頻繁重建cache的情況。

{
   "range": {
       "my_date": {
       "gte": "now-1y/h",
        "lte": "now-1y/h"
      }
    }
}

在原始Query里吧雹,將range filter寫成上述形式,手動(dòng)測(cè)試證實(shí)可行涂身,range filter有效期延長(zhǎng)到1小時(shí)雄卷,從而每個(gè)小時(shí)里,只需要為range filter重建2次Cache蛤售,至此問題解決丁鹉。


總結(jié):

  1. Cache并非建得越多越好,因?yàn)镃ache的生成和Evict會(huì)帶來額外的開銷悴能。特別是結(jié)果集非常大的filter揣钦,緩存的代價(jià)相對(duì)查詢本身可能非常高。
  2. ES 5.1.1開始取消了Terms filter Cache漠酿,因?yàn)門erms filter執(zhí)行非撤氚迹快,取消緩存多數(shù)情況下反而可以提高性能炒嘲。
  3. 大量用到Now-xxxd To Now這樣的Range filter時(shí)宇姚,可以借助round date技巧匈庭,提高Cache的有效期,減輕頻繁重建Cache帶來的性能問題浑劳。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末阱持,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子魔熏,更是在濱河造成了極大的恐慌衷咽,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,548評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蒜绽,死亡現(xiàn)場(chǎng)離奇詭異镶骗,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)滓窍,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,497評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門卖词,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人吏夯,你說我怎么就攤上這事此蜈。” “怎么了噪生?”我有些...
    開封第一講書人閱讀 167,990評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵裆赵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我跺嗽,道長(zhǎng)战授,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,618評(píng)論 1 296
  • 正文 為了忘掉前任桨嫁,我火速辦了婚禮植兰,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘璃吧。我一直安慰自己楣导,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,618評(píng)論 6 397
  • 文/花漫 我一把揭開白布畜挨。 她就那樣靜靜地躺著筒繁,像睡著了一般。 火紅的嫁衣襯著肌膚如雪巴元。 梳的紋絲不亂的頭發(fā)上毡咏,一...
    開封第一講書人閱讀 52,246評(píng)論 1 308
  • 那天,我揣著相機(jī)與錄音逮刨,去河邊找鬼呕缭。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的臊旭。 我是一名探鬼主播落恼,決...
    沈念sama閱讀 40,819評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼离熏!你這毒婦竟也來了佳谦?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,725評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤滋戳,失蹤者是張志新(化名)和其女友劉穎钻蔑,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體奸鸯,經(jīng)...
    沈念sama閱讀 46,268評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡咪笑,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,356評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了娄涩。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片窗怒。...
    茶點(diǎn)故事閱讀 40,488評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖蓄拣,靈堂內(nèi)的尸體忽然破棺而出扬虚,到底是詐尸還是另有隱情,我是刑警寧澤球恤,帶...
    沈念sama閱讀 36,181評(píng)論 5 350
  • 正文 年R本政府宣布辜昵,位于F島的核電站,受9級(jí)特大地震影響咽斧,放射性物質(zhì)發(fā)生泄漏堪置。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,862評(píng)論 3 333
  • 文/蒙蒙 一张惹、第九天 我趴在偏房一處隱蔽的房頂上張望舀锨。 院中可真熱鬧,春花似錦宛逗、人聲如沸坎匿。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,331評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽碑诉。三九已至彪腔,卻和暖如春侥锦,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背德挣。 一陣腳步聲響...
    開封第一講書人閱讀 33,445評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工恭垦, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,897評(píng)論 3 376
  • 正文 我出身青樓番挺,卻偏偏與公主長(zhǎng)得像唠帝,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子玄柏,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,500評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容