筆者在實際生產環境中常常遇到一些大文件的檢索,例如一些書籍內容,PDF文件等。今天這篇博客主要來探討下如何提高ES在檢索大文件的一些性能,經驗有限,算是一個小小的總結吧!html
ES創建索引完成全文檢索的前提是將待檢索的信息導入Elaticsearch。算法
項目中,有時候須要將一些掃描件、PDF文檔、Word、Excel、PPT等文檔內容導入Elasticsearch。api
好比:將《深刻理解Elasticsearch》這邊書導入ES,而這邊書的全文內容被識別後的大小可能爲3MB——5MB以上的字節。網絡
存入ES後是一個content字段,對這個content執行全文檢索&高亮顯示,就存在檢索效率低的問題,會耗時30S以上的時間。app
這點,做爲習慣了搜索引擎極速體驗的用戶,是不能忍的。elasticsearch
本文,詳細記錄了大文件的全文檢索性能問題排查及提高實踐方式。ide
從檢索症狀來看:工具
1)翻頁到1000+頁(每頁10條數據)以上,響應時間會比較長。post
2)當遇到某些文件的時候(過後分析得知是大文件),響應時間尤爲長,超過30S以上返回高亮結果。性能
baidu,360,搜狗等搜索引擎都不提供訪問末頁的請求方式。都是基於以下的請求方式:
經過點擊上一下、下一頁逐頁訪問。
這個從用戶的角度也很好理解,搜索引擎返回的前面都是相關度最高的,也是用戶最關心的信息。
Elasticsearch的默認支持的數據條數是10000條,能夠經過post請求修改。
最終,本步驟將支持ES最大返回值10000條數據,每頁10條,也就是共顯示1000頁數據。
【from + size機制】:當Elasticsearch響應請求時,它必須肯定docs的順序,排列響應結果。若是請求的頁數較少(假設每頁10個docs), Elasticsearch不會有什麼問題,可是若是頁數較大時,好比請求第100頁,Elasticsearch不得不取出第1頁到第100頁的全部docs,再去除第1頁到第99頁的docs,獲得第100頁的docs。
【scroll機制】:相對於from和size的分頁來講,使用scroll能夠模擬一個傳統數據的遊標,記錄當前讀取的文檔信息位置。這個分頁的用法,不是爲了實時查詢數據,而是爲了一次性查詢大量的數據(甚至是所有的數據)。
由於這個scroll至關於維護了一份當前索引段的快照信息,這個快照信息是你執行這個scroll查詢時的快照。在這個查詢後的任何新索引進來的數據,都不會在這個快照中查詢到。可是它相對於from和size,不是查詢全部數據而後剔除不要的部分,而是記錄一個讀取的位置,保證下一次快速繼續讀取。
from+size方式以及scroll方式優缺點對比:
1)對於from+size方式:當結果足夠大的時候,會大大加大內存和CPU的消耗。但,該方式使用很是方便。
2)對於scroll方式: 當結果足夠大的時候, scroll 性能更佳。可是不靈活和 scroll_id 難管理問題存在。
【from網絡】我的測試:當 結果足夠大的時候 產生 scroll_id 性能也不低。若是隻是一頁頁按照順序,scroll是極好的,可是若是是無規則的翻頁,那也是性能消耗極大的。
通過兩種機制對比,加之步驟1,限定了分頁數,最大1000頁。而且用戶支持主頁翻頁的方式,暫定仍是採用from+size方式。
若是後面步驟有問題,再考慮換成scorll機制。
當出現卡頓、卡死等性能低、用戶體驗差問題時,查看ES的日誌。
緣由分析:卡頓、卡死都是堆內存設置不足致使。
根據之間總結的高性能配置建議,果斷加堆內存,由16GB增長到最大值31GB。
堆內存使用比率能夠經過:cerebro 工具檢測性能。
1) 打印出DSL,能夠經過接口: searchSourceBuilder.toString()。
2) 新增profile參數,查看到底哪裏慢了。
profile API的目的是:將ES高層的ES請求拉平展開,直觀的讓你看到請求作了什麼,每一個細分點花了多少時間。
給你改善性能提供相關支撐工做。
使用舉例以下:
GET /_search { "profile": true, "query" : { "match" : { "message" : "message number" } } }
3) 換了全文接口api ,query_string改爲match query知足要求且速度有提高。
4)刪除某些查詢條件,在基礎數據不變的條件下,查看查詢速度是否快了(返回時間短了)。
驗證發現,當不返回content字段(_source控制)時,速度會變快。
當取消高亮字段處理,速度會更快。0.5秒以內返回結果。
至此,初步判定和高亮處理有關係。
經過論壇中網友的建議來看,都推薦對於大文件高亮使用: fast-vector-highlighter。
查詢官網文檔得知:
Elasticsearch高亮分爲三種方式:
官網明確支持,該方式匹配慢,若是出現性能問題,請考慮其餘高亮方式。
支持postings高亮方式,須要在mapping下添加以下信息:
"type": "text", "index_options" : "offsets"
添加完畢後,posting高亮方式將取代傳統的高亮方式。
posting高亮方式的特色:
1)速度快,不須要對高亮的文檔再分析。文檔越大,得到越高 性能 。
2)比fvh高亮方式須要的磁盤空間少。
3)將text文件分割成語句並對其高亮處理。對於天然語言發揮做用明顯,但對於html則否則。
4)將文檔視爲整個語料庫,並 使用BM25算法 爲該語料庫中的文檔打分。
使用舉例:
PUT /example { "mappings": { "doc" : { "properties": { "comment" : { "type": "text", "index_options" : "offsets" } } } } }
若是在mapping中的text類型字段下添加了以下信息:
"type": "text", "term_vector" : "with_positions_offsets"
fvh高亮方式將取代傳統的plain高亮方式。
fvh高亮方式的特色以下:
1)當文件>1MB(大文件)時候,尤爲適合fvh高亮方式。
2)自定義爲 boundary_scanner的掃描方式。
3) 設定了 term_vector to with_positions_offsets會增長索引的大小。
4)能聯合多字段匹配返回一個結果,詳見matched_fields。
5)對於不一樣的匹配類型分配不一樣的權重,如:pharse匹配比term匹配高。
舉例:
PUT /example { "mappings": { "doc" : { "properties": { "comment" : { "type": "text", "term_vector" : "with_positions_offsets" } } } } }
最終選型:fvh高亮方式。首先:新建了索引,按照fvh的方式對content字段新設置了mapping;其次經過以下方式進行索引數據同步:
POST /_reindex { "source": { "index": "test_index" }, "dest": { "index": "test_index_new" } }
實踐結果代表,一樣的大文件,本來檢索>40S,如今2S以內返回結果。
沒有改一行代碼,只修改了mapping,效率提高了近20倍。
相關參考:
[1] scroll和from size性能對比:
http://www.cnblogs.com/xing901022/archive/2016/03/16/5284902.html
[2]分解請求時間方式:
https://www.elastic.co/guide/en/elasticsearch/reference/5.4/search-profile.html