Периодические зависания

Добрый день! У нас возникла проблема с периодическим зависанием elastic. Такие зависания происходят в момент активного поиска + обновления индекса. В момент зависания elastic практически не отвечает на запросы, даже hot_threads отвечает более минуты. Вставка идет методом upsert как дочерних. У этого типа документа стоит флаг "eager_global_ordinals": true.

Возможно это как-то связанно с тем, что на диске осталось мало места?
Последние сообщения из лога:

[2017-11-16T08:45:59,321][INFO ][o.e.c.r.a.DiskThresholdMonitor] [WIN-K5I8RSP2SOQ] rerouting shards: [high disk watermark exceeded on one or more nodes]
[2017-11-16T08:45:59,323][WARN ][o.e.m.j.JvmGcMonitorService] [WIN-K5I8RSP2SOQ] [gc][old][54556][31] duration [1.1m], collections [1]/[1.1m], total [1.1m]/[30m], memory [26.3gb]->[23gb]/[29.3gb], all_pools {[young] [371kb]->[3.6mb]/[998.5mb]}{[survivor] [124.7mb]->[0b]/[124.7mb]}{[old] [26.2gb]->[23gb]/[28.2gb]}
[2017-11-16T08:45:59,323][WARN ][o.e.m.j.JvmGcMonitorService] [WIN-K5I8RSP2SOQ] [gc][54556] overhead, spent [1.1m] collecting in the last [1.1m]
[2017-11-16T08:46:00,323][WARN ][o.e.m.j.JvmGcMonitorService] [WIN-K5I8RSP2SOQ] [gc][54557] overhead, spent [590ms] collecting in the last [1s]
[2017-11-16T08:46:01,363][WARN ][o.e.m.j.JvmGcMonitorService] [WIN-K5I8RSP2SOQ] [gc][54558] overhead, spent [610ms] collecting in the last [1s]
[2017-11-16T08:46:02,383][WARN ][o.e.m.j.JvmGcMonitorService] [WIN-K5I8RSP2SOQ] [gc][54559] overhead, spent [644ms] collecting in the last [1s]
[2017-11-16T08:47:04,343][WARN ][o.e.m.j.JvmGcMonitorService] [WIN-K5I8RSP2SOQ] [gc][old][54560][32] duration [1m], collections [1]/[1m], total [1m]/[31m], memory [27.2gb]->[21gb]/[29.3gb], all_pools {[young] [5.2mb]->[6.4mb]/[998.5mb]}{[survivor] [124.7mb]->[0b]/[124.7mb]}{[old] [27.1gb]->[21gb]/[28.2gb]}
[2017-11-16T08:47:04,344][WARN ][o.e.m.j.JvmGcMonitorService] [WIN-K5I8RSP2SOQ] [gc][54560] overhead, spent [1m] collecting in the last [1m]
[2017-11-16T08:47:05,358][WARN ][o.e.m.j.JvmGcMonitorService] [WIN-K5I8RSP2SOQ] [gc][54561] overhead, spent [511ms] collecting in the last [1s]
[2017-11-16T08:47:07,129][WARN ][o.e.m.j.JvmGcMonitorService] [WIN-K5I8RSP2SOQ] [gc][54562] overhead, spent [1s] collecting in the last [1.7s]
[2017-11-16T08:47:08,410][WARN ][o.e.m.j.JvmGcMonitorService] [WIN-K5I8RSP2SOQ] [gc][54563] overhead, spent [812ms] collecting in the last [1.2s]

Вот что показывает hot_threads в моменты зависания:
Не получается вставить целиком.

Hot threads at 2017-11-16T12:28:49.915Z, interval=500ms, busiestThreads=3, ignoreIdleThreads=true:

37.5% (187.5ms out of 500ms) cpu usage by thread 'elasticsearch[WIN-K5I8RSP2SOQ][search][T#4]'
3/10 snapshots sharing following 38 elements
org.apache.lucene.store.ByteBufferIndexInput.clone(ByteBufferIndexInput.java:249)
org.apache.lucene.store.ByteBufferIndexInput$SingleBufferImpl.clone(ByteBufferIndexInput.java:347)
org.apache.lucene.codecs.lucene50.Lucene50PostingsReader$BlockPostingsEnum.(Lucene50PostingsReader.java:536)
org.apache.lucene.codecs.lucene50.Lucene50PostingsReader.postings(Lucene50PostingsReader.java:220)
org.apache.lucene.codecs.blocktree.SegmentTermsEnum.postings(SegmentTermsEnum.java:1002)
org.apache.lucene.search.spans.SpanTermQuery$SpanTermWeight.getSpans(SpanTermQuery.java:119)
org.apache.lucene.search.spans.SpanOrQuery$SpanOrWeight.getSpans(SpanOrQuery.java:155)
org.apache.lucene.search.spans.SpanNearQuery$SpanNearWeight.getSpans(SpanNearQuery.java:213)
org.apache.lucene.search.spans.SpanWeight.scorer(SpanWeight.java:133)
org.apache.lucene.search.spans.SpanWeight.scorer(SpanWeight.java:38)
org.apache.lucene.search.Weight.scorerSupplier(Weight.java:126)
org.apache.lucene.search.BooleanWeight.scorerSupplier(BooleanWeight.java:400)
org.apache.lucene.search.BooleanWeight.scorerSupplier(BooleanWeight.java:400)
org.apache.lucene.search.BooleanWeight.scorer(BooleanWeight.java:381)
org.apache.lucene.search.Weight.bulkScorer(Weight.java:160)
org.apache.lucene.search.BooleanWeight.bulkScorer(BooleanWeight.java:375)
org.apache.lucene.search.IndexSearcher.search(IndexSearcher.java:665)
org.apache.lucene.search.IndexSearcher.search(IndexSearcher.java:472)
org.apache.lucene.search.join.JoinUtil.createJoinQuery(JoinUtil.java:533)
org.elasticsearch.join.query.HasChildQueryBuilder$LateParsingQuery.rewrite(HasChildQueryBuilder.java:437)
org.apache.lucene.search.BooleanQuery.rewrite(BooleanQuery.java:265)
org.apache.lucene.search.BooleanQuery.rewrite(BooleanQuery.java:265)
org.apache.lucene.search.IndexSearcher.rewrite(IndexSearcher.java:683)
org.elasticsearch.search.internal.ContextIndexSearcher.rewrite(ContextIndexSearcher.java:106)
org.elasticsearch.search.DefaultSearchContext.preProcess(DefaultSearchContext.java:251)
org.elasticsearch.search.query.QueryPhase.preProcess(QueryPhase.java:95)
org.elasticsearch.search.SearchService.createContext(SearchService.java:497)
org.elasticsearch.search.SearchService.createAndPutContext(SearchService.java:461)
org.elasticsearch.search.SearchService.executeQueryPhase(SearchService.java:257)
org.elasticsearch.action.search.SearchTransportService$6.messageReceived(SearchTransportService.java:340)
org.elasticsearch.action.search.SearchTransportService$6.messageReceived(SearchTransportService.java:337)
org.elasticsearch.transport.RequestHandlerRegistry.processMessageReceived(RequestHandlerRegistry.java:69)
org.elasticsearch.transport.TransportService$7.doRun(TransportService.java:644)
org.elasticsearch.common.util.concurrent.ThreadContext$ContextPreservingAbstractRunnable.doRun(ThreadContext.java:638)
org.elasticsearch.common.util.concurrent.AbstractRunnable.run(AbstractRunnable.java:37)
java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
java.lang.Thread.run(Unknown Source)

Есть какие-нибудь варианты, что можно подкрутить или исправить?

Хотя, я отключил все обновления и ситуация такая же. В логе видно, что постепенно растет время сборки мусора. "heap_used_percent" колеблется в районе 74-79%. Под кучу выделено максимально возможное количество памяти ("heap_max": "29.3gb").

[2017-11-16T10:23:11,479][INFO ][o.e.c.r.a.DiskThresholdMonitor] [WIN-K5I8RSP2SOQ] rerouting shards: [high disk watermark exceeded on one or more nodes]
[2017-11-16T10:23:12,595][INFO ][o.e.m.j.JvmGcMonitorService] [WIN-K5I8RSP2SOQ] [gc][834] overhead, spent [430ms] collecting in the last [1.2s]
[2017-11-16T10:23:13,596][INFO ][o.e.m.j.JvmGcMonitorService] [WIN-K5I8RSP2SOQ] [gc][835] overhead, spent [343ms] collecting in the last [1s]
[2017-11-16T10:23:14,720][INFO ][o.e.m.j.JvmGcMonitorService] [WIN-K5I8RSP2SOQ] [gc][836] overhead, spent [317ms] collecting in the last [1.1s]
[2017-11-16T10:23:16,874][INFO ][o.e.m.j.JvmGcMonitorService] [WIN-K5I8RSP2SOQ] [gc][838] overhead, spent [401ms] collecting in the last [1.1s]
[2017-11-16T10:23:18,266][WARN ][o.e.m.j.JvmGcMonitorService] [WIN-K5I8RSP2SOQ] [gc][839] overhead, spent [993ms] collecting in the last [1.3s]
[2017-11-16T10:23:19,549][WARN ][o.e.m.j.JvmGcMonitorService] [WIN-K5I8RSP2SOQ] [gc][840] overhead, spent [683ms] collecting in the last [1.2s]
[2017-11-16T10:23:20,592][INFO ][o.e.m.j.JvmGcMonitorService] [WIN-K5I8RSP2SOQ] [gc][841] overhead, spent [462ms] collecting in the last [1s]
[2017-11-16T10:23:21,593][INFO ][o.e.m.j.JvmGcMonitorService] [WIN-K5I8RSP2SOQ] [gc][842] overhead, spent [377ms] collecting in the last [1s]
[2017-11-16T10:23:22,668][WARN ][o.e.m.j.JvmGcMonitorService] [WIN-K5I8RSP2SOQ] [gc][843] overhead, spent [546ms] collecting in the last [1s]
[2017-11-16T10:23:23,668][INFO ][o.e.m.j.JvmGcMonitorService] [WIN-K5I8RSP2SOQ] [gc][844] overhead, spent [262ms] collecting in the last [1s]
[2017-11-16T10:24:12,898][WARN ][o.e.m.j.JvmGcMonitorService] [WIN-K5I8RSP2SOQ] [gc][old][845][9] duration [48.7s], collections [1]/[49.2s], total [48.7s]/[1.9m], memory [28.8gb]->[19.6gb]/[29.3gb], all_pools {[young] [983.6mb]->[2.8mb]/[998.5mb]}{[survivor] [124.7mb]->[0b]/[124.7mb]}{[old] [27.8gb]->[19.6gb]/[28.2gb]}
[2017-11-16T10:24:12,898][WARN ][o.e.m.j.JvmGcMonitorService] [WIN-K5I8RSP2SOQ] [gc][845] overhead, spent [48.8s] collecting in the last [49.2s]
[2017-11-16T10:24:13,899][INFO ][o.e.m.j.JvmGcMonitorService] [WIN-K5I8RSP2SOQ] [gc][846] overhead, spent [422ms] collecting in the last [1s]
[2017-11-16T10:24:14,280][WARN ][o.e.c.r.a.DiskThresholdMonitor] [WIN-K5I8RSP2SOQ] high disk watermark [90%] exceeded on [Nu_NmpzIT82FmAkDMK_VLw][WIN-K5I8RSP2SOQ][D:\data\nodes\0] free: 59.8gb[6.6%], shards will be relocated away from this node
[2017-11-16T10:24:14,280][INFO ][o.e.c.r.a.DiskThresholdMonitor] [WIN-K5I8RSP2SOQ] rerouting shards: [high disk watermark exceeded on one or more nodes]
[2017-11-16T10:24:14,901][INFO ][o.e.m.j.JvmGcMonitorService] [WIN-K5I8RSP2SOQ] [gc][847] overhead, spent [262ms] collecting in the last [1s]
[2017-11-16T10:24:22,940][INFO ][o.e.m.j.JvmGcMonitorService] [WIN-K5I8RSP2SOQ] [gc][855] overhead, spent [495ms] collecting in the last [1s]
[2017-11-16T10:24:27,063][INFO ][o.e.m.j.JvmGcMonitorService] [WIN-K5I8RSP2SOQ] [gc][859] overhead, spent [343ms] collecting in the last [1s]
[2017-11-16T10:24:28,667][INFO ][o.e.m.j.JvmGcMonitorService] [WIN-K5I8RSP2SOQ] [gc][860] overhead, spent [558ms] collecting in the last [1.6s]
[2017-11-16T10:24:29,668][INFO ][o.e.m.j.JvmGcMonitorService] [WIN-K5I8RSP2SOQ] [gc][861] overhead, spent [431ms] collecting in the last [1s]
[2017-11-16T10:24:31,670][INFO ][o.e.m.j.JvmGcMonitorService] [WIN-K5I8RSP2SOQ] [gc][863] overhead, spent [444ms] collecting in the last [1s]
[2017-11-16T10:24:32,671][INFO ][o.e.m.j.JvmGcMonitorService] [WIN-K5I8RSP2SOQ] [gc][864] overhead, spent [386ms] collecting in the last [1s]
[2017-11-16T10:25:28,701][WARN ][o.e.m.j.JvmGcMonitorService] [WIN-K5I8RSP2SOQ] [gc][old][865][10] duration [55.9s], collections [1]/[56s], total [55.9s]/[2.8m], memory [28.6gb]->[22gb]/[29.3gb], all_pools {[young] [754.4mb]->[9mb]/[998.5mb]}{[survivor] [124.7mb]->[0b]/[124.7mb]}{[old] [27.7gb]->[22gb]/[28.2gb]}
[2017-11-16T10:25:28,701][WARN ][o.e.m.j.JvmGcMonitorService] [WIN-K5I8RSP2SOQ] [gc][865] overhead, spent [55.9s] collecting in the last [56s]
[2017-11-16T10:25:29,832][INFO ][o.e.m.j.JvmGcMonitorService] [WIN-K5I8RSP2SOQ] [gc][866] overhead, spent [447ms] collecting in the last [1.1s]
[2017-11-16T10:25:29,896][WARN ][o.e.c.r.a.DiskThresholdMonitor] [WIN-K5I8RSP2SOQ] high disk watermark [90%] exceeded on [Nu_NmpzIT82FmAkDMK_VLw][WIN-K5I8RSP2SOQ][D:\data\nodes\0] free: 59.8gb[6.6%], shards will be relocated away from this node
[2017-11-16T10:25:29,896][INFO ][o.e.c.r.a.DiskThresholdMonitor] [WIN-K5I8RSP2SOQ] rerouting shards: [high disk watermark exceeded on one or more nodes]
[2017-11-16T10:25:30,833][INFO ][o.e.m.j.JvmGcMonitorService] [WIN-K5I8RSP2SOQ] [gc][867] overhead, spent [359ms] collecting in the last [1s]
[2017-11-16T10:25:31,846][INFO ][o.e.m.j.JvmGcMonitorService] [WIN-K5I8RSP2SOQ] [gc][868] overhead, spent [336ms] collecting in the last [1s]
[2017-11-16T10:25:33,023][INFO ][o.e.m.j.JvmGcMonitorService] [WIN-K5I8RSP2SOQ] [gc][869] overhead, spent [536ms] collecting in the last [1.1s]
[2017-11-16T10:25:35,301][WARN ][o.e.m.j.JvmGcMonitorService] [WIN-K5I8RSP2SOQ] [gc][871] overhead, spent [648ms] collecting in the last [1.2s]
[2017-11-16T10:25:36,366][WARN ][o.e.m.j.JvmGcMonitorService] [WIN-K5I8RSP2SOQ] [gc][872] overhead, spent [634ms] collecting in the last [1s]

А можно на /_nodes/stats взглянуть? Хотелось бы понять, куда эта память уходит.

Вы не могли бы поместить этот запрос в gist и прислать ссылку?

Затем, в логах появляется ошибки и эластик падает. Вижу что это из-за сборщика мусора.

[2017-11-16T17:05:31,438][WARN ][o.e.m.j.JvmGcMonitorService] [WIN-K5I8RSP2SOQ] [gc][old][1109][95] duration [46.6s], collections [1]/[47.2s], total [46.6s]/[1.1h], memory [29.3gb]->[29.3gb]/[29.3gb], all_pools {[young] [998.5mb]->[998.5mb]/[998.5mb]}{[survivor] [107.4mb]->[119.9mb]/[124.7mb]}{[old] [28.2gb]->[28.2gb]/[28.2gb]}
[2017-11-16T17:05:31,438][WARN ][o.e.m.j.JvmGcMonitorService] [WIN-K5I8RSP2SOQ] [gc][1109] overhead, spent [46.6s] collecting in the last [47.2s]
[2017-11-16T17:06:10,511][WARN ][o.e.m.j.JvmGcMonitorService] [WIN-K5I8RSP2SOQ] [gc][old][1110][96] duration [39s], collections [1]/[38.6s], total [39s]/[1.2h], memory [29.3gb]->[29.3gb]/[29.3gb], all_pools {[young] [998.5mb]->[998.5mb]/[998.5mb]}{[survivor] [119.9mb]->[123.3mb]/[124.7mb]}{[old] [28.2gb]->[28.2gb]/[28.2gb]}
[2017-11-16T17:06:10,513][WARN ][o.e.m.j.JvmGcMonitorService] [WIN-K5I8RSP2SOQ] [gc][1110] overhead, spent [39s] collecting in the last [38.6s]
[2017-11-16T17:07:03,008][WARN ][o.e.m.j.JvmGcMonitorService] [WIN-K5I8RSP2SOQ] [gc][old][1111][97] duration [52.4s], collections [1]/[52.9s], total [52.4s]/[1.2h], memory [29.3gb]->[29.3gb]/[29.3gb], all_pools {[young] [998.5mb]->[998.5mb]/[998.5mb]}{[survivor] [123.3mb]->[124.3mb]/[124.7mb]}{[old] [28.2gb]->[28.2gb]/[28.2gb]}
[2017-11-16T17:07:03,008][WARN ][o.e.m.j.JvmGcMonitorService] [WIN-K5I8RSP2SOQ] [gc][1111] overhead, spent [52.4s] collecting in the last [52.9s]
[2017-11-16T17:21:37,280][WARN ][o.e.m.j.JvmGcMonitorService] [WIN-K5I8RSP2SOQ] [gc][old][1112][109] duration [8.5m], collections [12]/[14.5m], total [8.5m]/[1.3h], memory [29.3gb]->[27.5gb]/[29.3gb], all_pools {[young] [998.5mb]->[52.4mb]/[998.5mb]}{[survivor] [124.3mb]->[0b]/[124.7mb]}{[old] [28.2gb]->[27.4gb]/[28.2gb]}
[2017-11-16T17:21:37,280][WARN ][o.e.m.j.JvmGcMonitorService] [WIN-K5I8RSP2SOQ] [gc][1112] overhead, spent [8.5m] collecting in the last [14.5m]
[2017-11-16T17:21:37,292][WARN ][o.e.c.s.ClusterService ] [WIN-K5I8RSP2SOQ] cluster state update task [cluster_reroute (api)] took [16m] above the warn threshold of 30s
[2017-11-16T17:21:37,300][ERROR][o.e.b.ElasticsearchUncaughtExceptionHandler] [WIN-K5I8RSP2SOQ] fatal error in thread [elasticsearch[WIN-K5I8RSP2SOQ][search][T#7]], exiting
java.lang.OutOfMemoryError: Java heap space
at org.apache.lucene.codecs.lucene50.Lucene50PostingsReader$BlockPostingsEnum.(Lucene50PostingsReader.java:475) ~[lucene-core-6.6.1.jar:6.6.1 9aa465a89b64ff2dabe7b4d50c472de32c298683 - varunthacker - 2017-08-29 21:54:39]

Вот ссылка https://gist.github.com/anonymous/c1b72e5ab0d983981a84e87eb62567cc
Там _state, _tasks, hot_threads и log/

Все данные приведены на момент зависания

Вы ищите с 30-и минутным скроллом и этот скролл, похоже, никогда на закрываете и за пол часа у вас нода падает, так что сами эти скроллы почистится не успевают. Хотя, может она и падает потому, что чистка через пол часа начинается и занимает слишком много времени и поэтому все тормозить начинает.

В любом случае, давайте со скроллами разберемся. Она вам, вообще, зачем?

Скролл использую для кеша поискового запроса, например, пользователь нажал на кнопку искать, его запрос выполнился и в течении 30 мин он может переходить по страницам с помощью скролла, а не нового запроса.

Хочу немного рассказать, о том, как устроена наша система. У пользователей есть набор сохраненных фильтров (порядка 40) включая поиск по тексту, который происходит по 20 млн документов, каждый документ весит порядка 300-500 Кб. Эти документы идут как parent/child к другим документам которых меньше, порядка 4 млн. При поиске по тексту используются prefix и span_near для поиска по фразам.

Теперь о способе тестирования. Я провожу нагрузочное тестирование по сохраненным пользователями настройкам. Пробую в 2 потока. Сейчас попробовал отключить скролл, ситуация повторяется, и проходит не 30 минут, а 100 запросов, после чего эластик уходит в жесткие тормоза и перестает отвечать на запросы. В этот момент "heap_used_percent": 99.

Если не скролл, то не знаю. Ничего, больше подозрительного в stats не вижу. Надо в heapdump смотреть.

Сегодня в результате тестов у меня происходили зависания и на 52% использования кучи. Я отключил скролл и сортировку. У нас есть второй такой же сервер, где индексируется такой же индекс. На нем таких проблем я не выявил. Разница между ними в версии эластика.

Могут ли возникать такие проблемы при использовании span_near + prefix на 19 млн. документов? Объясните, мне пожалуйста, могут ли тяжелые поиски вызывать падение службы или же такие действия должны пресекаться внутренними механизмами защиты и то что происходит у меня это не стандартная ситуация?

Вот что показывает дамп, если это поможет понять причины.

Да, теперь причина понятна - https://github.com/elastic/elasticsearch/issues/27432

Если я правильно понял, применение Multi Term Query Rewrite должно решить проблему с переполнением кучи? Хотя, скорее всего, мне нужен способ наоборот исключить высокочастотные слова из префиксного поиска. Есть возможность применить cutoff_frequency или аналогичные функции для prefix?

Если я правильно понял, применение Multi Term Query Rewrite должно решить проблему с переполнением кучи?

Проблема в том, что этот prefix в данном контексте по умолчанию превращается в поиск по всем терминам, скролл эту проблему ухудшает, потому что держит эти термины в памяти дольше, чем нужно. С Multi Term Query Rewrite можно уменьшить количество терминов, и таким образом уменьшить память.

Есть возможность применить cutoff_frequency или аналогичные функции для prefix?

Такого нет. Но если бы и был, то я не думаю, что это привело бы к хорошему результату. Я, вообще, не понимаю, почему вы ищете по префиксу. Судя по примерам запросов в логе, вам нужен просто стеммер и, может быть, decompounder. Но если очень надо чтобы был именно префикс, то может попробовать проиндексировать с edgeNGram все?

Судя по примерам запросов в логе, вам нужен просто стеммер и, может быть, decompounder

Префикс используется для того, что бы не работать с ошибками стеммера. Мы работаем с документами в которых содержится достаточно большой процент ошибок. Да и изначально так сложилось, что пользователи настраивали поиск с помощью стеммированного варианта слова - это надежно, теперь, когда клиентов много, этого уже не исправить.

С Multi Term Query Rewrite можно уменьшить количество терминов, и таким образом уменьшить память

А проблему нехватки памяти решается увеличением количества нод? Получается, что каждая нода будет работать с меньшим объемом данных, что приведет к уменьшению потребления памяти. Но, мне не ясен такой принцип работы, в результате, данные обработки запроса со всех нод, собираются на одной, что там будет с памятью?

Да, это уменьшит количество запросов на каждую ноду, так что в какой-то степени должно помочь.

Но, мне не ясен такой принцип работы, в результате, данные обработки запроса со всех нод, собираются на одной, что там будет с памятью?

Эта память нужна на шарде во время выполнения запроса к этой шарде, а не во время сборки ответов с каждой шарды.

Кстати, а сколько у Вас шард в этом индексе?

Сейчас количество шард равно 14, каждая, примерно, по 45Гб.

Я думаю, если уменьшить количество шард, то количество требуемой памяти тоже уменьшиться.

Игорь, если я правильно понял, то при поиске, каждая шарда формирует свой, независимый, список терминов и помещает его в память? Т.е. если у меня 14 шард, то с них я получу в 14 раз больший объем потребления памяти чем при 1?

И по поводу добавления второй ноды, если я ее добавлю в кластер, то каждая нода будет работать с еще меньшим количеством шард, что положительно скажется на памяти. Я правильно думаю?

Почти. Обычно термины распределены по закону Ципфа поэтому некоторые термины будут повторяться на всех шардах, но многие будут встречаться только на одной или двух. Поэтому объем потребления памяти уменьшиться но не в 14 раз. Может раз 5-7 или меньше. Зависит от того, как у вас термины распределены.

И по поводу добавления второй ноды, если я ее добавлю в кластер, то каждая нода будет работать с еще меньшим количеством шард, что положительно скажется на памяти. Я правильно думаю?

Если у этого индекса настроены реплики, то количество шард будет такое-же, но вот количество одновременных запросов уменьшится.