# A question over the way we use maxSeqNoOfUpdatesOrDeletes for optimization

**URL:** <https://discuss.elastic.co/t/a-question-over-the-way-we-use-maxseqnoofupdatesordeletes-for-optimization/222636>\
**Category:** Elasticsearch\
**Created:** [March 9, 2020, 3:48am UTC](https://discuss.elastic.co/t/a-question-over-the-way-we-use-maxseqnoofupdatesordeletes-for-optimization/222636 "2020-03-09T03:48:58Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![iamorchid](https://avatars.discourse-cdn.com/v4/letter/i/bbce88/32.png) [@iamorchid](https://discuss.elastic.co/u/iamorchid)\
**Post date:** [March 9, 2020, 3:48am UTC](https://discuss.elastic.co/t/a-question-over-the-way-we-use-maxseqnoofupdatesordeletes-for-optimization/222636/1 "2020-03-09T03:48:58Z")

</div>

Currently, I see that we are using the following check to decide if we can optimize indexing of new documents on replicas ([ApendOnly Optimization for non-primary](https://github.com/elastic/elasticsearch/blob/7.6/server/src/main/java/org/elasticsearch/index/engine/InternalEngine.java#L1003)).

```
if (maxSeqNoOfUpdatesOrDeletes <= localCheckpointTracker.getProcessedCheckpoint()) {
    assert maxSeqNoOfUpdatesOrDeletes < index.seqNo() : index.seqNo() + ">=" + maxSeqNoOfUpdatesOrDeletes;
    plan = IndexingStrategy.optimizedAppendOnly(index.version());
}

```

However, I think we can perhaps loosen the constraint using **maxSeqNoOfUpdatesOrDeletes \< index.seqNo()** based on my analysis below.

For an operation O, if it's an index update on exiting doc or a delete, the primary would update its MSU to some value \>= seqno(O) before replicating this operation O and its latest MSU to other replicas. Thus when replicas see that seqno(O) \<= its maintained MSU, they know that append-only optimazation can not be applied since O could be an UPDATE. On the other hand, if they see seqno(O) \> their latest MSU, it can be sure that index operation O is not an UPDATE but add a new doc.

For the case LCP \< MSU, if a future operation O' with seqno(O') \> seqno(O) is processed before operation O on replica, we should have seqno(O) \< seqno(O') \<= MSU(O') \<= MSU. Thus we can also avoid creating duplicated doc by not applying optimization for O when out-of-order happens.

Not sure if it's reliable enough to use maxSeqNoOfUpdatesOrDeletes \< index.seqNo() to decide to use optimization or not. It would be helpful if some cases/examples can be used to illustrage why this doesn't work.

Thanks

---

<div class="post-metadata">

**Author:** ![HenningAndersen](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/henningandersen/32/48188_2.png) [@HenningAndersen](https://discuss.elastic.co/u/HenningAndersen)\
**Post date:** [March 9, 2020, 8:17am UTC](https://discuss.elastic.co/t/a-question-over-the-way-we-use-maxseqnoofupdatesordeletes-for-optimization/222636/2 "2020-03-09T08:17:49Z")

</div>

Hi @iamorchid,

an example where this would go wrong is if the previous op were a delete. Consider:

```auto
seqNo(O') < seqNo(O)

```

where O' is a deletion. When replicating O, MSU would be seqNo(O'). If O arrives on replica before O', O would be added, not updated, leading to a duplicate.

By checking MSU \<= LCP, we only apply the optimization if we processed every update or delete on replica already, avoiding this issue.

---

<div class="post-metadata">

**Author:** ![iamorchid](https://avatars.discourse-cdn.com/v4/letter/i/bbce88/32.png) [@iamorchid](https://discuss.elastic.co/u/iamorchid)\
**Post date:** [March 9, 2020, 8:47am UTC](https://discuss.elastic.co/t/a-question-over-the-way-we-use-maxseqnoofupdatesordeletes-for-optimization/222636/3 "2020-03-09T08:47:41Z")

</div>

Hi @HenningAndersen

Sorry, not quite understand why the out-of-order would cause duplicate. Let's say we have two cases here for deletion O' and index operation O.

**1. The same doc doesn't exist in Lucene before we execute O' and O**  
**a)** if we execute O' and O in order, we would end up with a soft-deleted doc and a new doc in Lucene。  
**b)** if we execute O (MSU=seqno(O')) before O'(MSU=seqno(O')), if the optimizaiton rule I suppose is used, O would add a new doc into Lucene and then O' would be marked as stale, which also creates a soft-deleted doc in Lucene.  
So I think a) and b) would end up with the same state for this case.

**2. The same doc exists in Lucene before we execute O' and O**  
**a)** if we execute O' and O in order, O' would create two soft-deleted doc (one for the previous existing doc and the other for the doc in O') in Lucene while O would add a new doc.  
**b)** if we execute O (MSU=seqno(O')) before O', if the optimizaiton rule I suppose is used, O would convert the existing doc into a soft-deleted one and add a new doc in Lucene while O' would add another soft-deleted doc in Lucene since O' now is stale.  
For this case, it looks a) and b) seems still to end up with the same state.

Maybe I have misunderstood something here.

---

<div class="post-metadata">

**Author:** ![HenningAndersen](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/henningandersen/32/48188_2.png) [@HenningAndersen](https://discuss.elastic.co/u/HenningAndersen)\
**Post date:** [March 9, 2020, 9:10am UTC](https://discuss.elastic.co/t/a-question-over-the-way-we-use-maxseqnoofupdatesordeletes-for-optimization/222636/4 "2020-03-09T09:10:41Z")

</div>

Hi @iamorchid,

this is the interesting part:

> [@iamorchid](#):
>
> **b)** if we execute O (MSU=seqno(O')) before O', if the optimizaiton rule I suppose is used, O would convert the existing doc into a soft-deleted one and add a new doc in Lucene while O' would add another soft-deleted doc in Lucene since O' now is stale.

If I understand your rule correct, you would check seqNo(O) \> MSU and if so, use the append only optimization. In that case, indexing O would only do the "add" and not do the soft-delete of the existing doc. Meaning this part of the 2b does not hold true:

> O would convert the existing doc into a soft-deleted one

---

<div class="post-metadata">

**Author:** ![iamorchid](https://avatars.discourse-cdn.com/v4/letter/i/bbce88/32.png) [@iamorchid](https://discuss.elastic.co/u/iamorchid)\
**Post date:** [March 9, 2020, 9:16am UTC](https://discuss.elastic.co/t/a-question-over-the-way-we-use-maxseqnoofupdatesordeletes-for-optimization/222636/5 "2020-03-09T09:16:10Z")

</div>

Ah, right. The optimization doesn't check version map. Got it. Thanks @HenningAndersen so much.

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/elastic/original/3X/1/a/1ac57faf039f6b580b3f104ef42a2a89e41014de.png) [@system](https://discuss.elastic.co/u/system)\
**Post date:** [April 6, 2020, 9:16am UTC](https://discuss.elastic.co/t/a-question-over-the-way-we-use-maxseqnoofupdatesordeletes-for-optimization/222636/6 "2020-04-06T09:16:13Z")

</div>

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.
