[ 
https://issues.apache.org/jira/browse/SOLR-17976?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Yue Yu updated SOLR-17976:
--------------------------
    Description: 
In the mergeIds function of QueryComponent, this heap ShardFieldSortedHitQueue 
is used to order the ShardDoc. However, in the *lessThan* function:

 
{code:java}
protected boolean lessThan(ShardDoc docA, ShardDoc docB) {
// If these docs are from the same shard, then the relative order // is how 
they appeared in the response from that shard. if (Objects.equals(docA.shard, 
docB.shard)) {
// if docA has a smaller position, it should be "larger" so it // comes before 
docB. // This will handle sorting by docid within the same shard // comment 
this out to test comparators. return !(docA.orderInShard < docB.orderInShard);
}
// run comparators final int n = comparators.length;
int c = 0;
for (int i = 0; i < n && c == 0; i++) {
c =
(fields[i].getReverse())
? comparators[i].compare(docB, docA)
: comparators[i].compare(docA, docB);
}
// solve tiebreaks by comparing shards (similar to using docid) // smaller 
docid's beat larger ids, so reverse the natural ordering if (c == 0) {
c = -docA.shard.compareTo(docB.shard);
}
return c < 0;
}
{code}
The last tie-breaking logic is comparing ShardDoc.shard:
{code:java}
// solve tiebreaks by comparing shards (similar to using docid)// smaller 
docid's beat larger ids, so reverse the natural orderingif (c == 0) {
c = -docA.shard.compareTo(docB.shard);
}{code}

 Here ShardDoc.shard contains node ip as well as shard name, for example: 
[http://127.0.0.1:8983/solr/my_collection_shard1_replica_n1]
Consider this setup: 1 collection with 2 shard 2 replica running on a 2 nodes 
cluster. For the same query, we may have documents coming from the following 
core combinations:
 # [http://node1_ip:8983/solr/my_collection_shard1_replica_n1] + 
[http://node2_ip:8983/solr/my_collection_shard2_replica_n2]
 # [http://node2_ip:8983/solr/my_collection_shard1_replica_n2] + 
[http://node1_ip:8983/solr/my_collection_shard2_replica_n1]

Hence the same request may have different document rankings when there are 
documents from both shards with the same scores. This can get worse with more 
nodes/shards/replicas. 
I'm wondering if we should just use the shard name for tie breaking instead (no 
node ip), if that's possible

  was:
In the mergeIds function of QueryComponent, this heap ShardFieldSortedHitQueue 
is used to order the ShardDoc. However, in the *lessThan* function:

{color:#cf8e6d}protected boolean {color}{color:#56a8f5}lessThan{color}(ShardDoc 
docA, ShardDoc docB) {
{color:#7a7e85}// If these docs are from the same shard, then the relative order
{color}{color:#7a7e85} // is how they appeared in the response from that shard.
{color}{color:#7a7e85} {color}{color:#cf8e6d}if 
{color}(Objects.equals(docA.{color:#c77dbb}shard{color}, 
docB.{color:#c77dbb}shard{color})) {
{color:#7a7e85}// if docA has a smaller position, it should be "larger" so it
{color}{color:#7a7e85} // comes before docB.
{color}{color:#7a7e85} // This will handle sorting by docid within the same 
shard
{color}{color:#7a7e85}
{color}{color:#7a7e85} // comment this out to test comparators.
{color}{color:#7a7e85} {color}{color:#cf8e6d}return 
{color}!(docA.{color:#c77dbb}orderInShard {color}< 
docB.{color:#c77dbb}orderInShard{color});
}

{color:#7a7e85}// run comparators
{color}{color:#7a7e85} {color}{color:#cf8e6d}final int {color}n = 
{color:#c77dbb}comparators{color}.{color:#c77dbb}length{color};
{color:#cf8e6d}int {color}c = {color:#2aacb8}0{color};
{color:#cf8e6d}for {color}({color:#cf8e6d}int {color}i = 
{color:#2aacb8}0{color}; i < n && c == {color:#2aacb8}0{color}; i++) {
c =
({color:#c77dbb}fields{color}[i].getReverse())
? {color:#c77dbb}comparators{color}[i].compare(docB, docA)
: {color:#c77dbb}comparators{color}[i].compare(docA, docB);
}

{color:#7a7e85}// solve tiebreaks by comparing shards (similar to using docid)
{color}{color:#7a7e85} // smaller docid's beat larger ids, so reverse the 
natural ordering
{color}{color:#7a7e85} {color}{color:#cf8e6d}if {color}(c == 
{color:#2aacb8}0{color}) {
c = 
-docA.{color:#c77dbb}shard{color}.compareTo(docB.{color:#c77dbb}shard{color});
}

{color:#cf8e6d}return {color}c < {color:#2aacb8}0{color};
}The last tie-breaking logic is comparing ShardDoc.shard:
{color:#7a7e85}// solve tiebreaks by comparing shards (similar to using docid)
{color}{color:#7a7e85}// smaller docid's beat larger ids, so reverse the 
natural ordering
{color}{color:#cf8e6d}if {color}(c == {color:#2aacb8}0{color}) {
c = 
-docA.{color:#c77dbb}shard{color}.compareTo(docB.{color:#c77dbb}shard{color});
}
 
Here ShardDoc.shard contains node ip as well as shard name, for example: 
[http://127.0.0.1:8983/solr/my_collection_shard1_replica_n1]
Consider this setup: 1 collection with 2 shard 2 replica running on a 2 nodes 
cluster. For the same query, we may have documents coming from the following 
core combinations:
 # [http://node1_ip:8983/solr/my_collection_shard1_replica_n1] + 
[http://node2_ip:8983/solr/my_collection_shard2_replica_n2]
 # [http://node2_ip:8983/solr/my_collection_shard1_replica_n2] + 
[http://node1_ip:8983/solr/my_collection_shard2_replica_n1]

Hence the same request may have different document rankings when there are 
documents from both shards with the same scores. This can get worse with more 
nodes/shards/replicas. 
I'm wondering if we should just use the shard name for tie breaking instead (no 
node ip), if that's possible


> Solr 9.5 distributed search tie breaking logic is non-deterministic
> -------------------------------------------------------------------
>
>                 Key: SOLR-17976
>                 URL: https://issues.apache.org/jira/browse/SOLR-17976
>             Project: Solr
>          Issue Type: Bug
>          Components: SolrCloud
>            Reporter: Yue Yu
>            Priority: Major
>
> In the mergeIds function of QueryComponent, this heap 
> ShardFieldSortedHitQueue is used to order the ShardDoc. However, in the 
> *lessThan* function:
>  
> {code:java}
> protected boolean lessThan(ShardDoc docA, ShardDoc docB) {
> // If these docs are from the same shard, then the relative order // is how 
> they appeared in the response from that shard. if (Objects.equals(docA.shard, 
> docB.shard)) {
> // if docA has a smaller position, it should be "larger" so it // comes 
> before docB. // This will handle sorting by docid within the same shard // 
> comment this out to test comparators. return !(docA.orderInShard < 
> docB.orderInShard);
> }
> // run comparators final int n = comparators.length;
> int c = 0;
> for (int i = 0; i < n && c == 0; i++) {
> c =
> (fields[i].getReverse())
> ? comparators[i].compare(docB, docA)
> : comparators[i].compare(docA, docB);
> }
> // solve tiebreaks by comparing shards (similar to using docid) // smaller 
> docid's beat larger ids, so reverse the natural ordering if (c == 0) {
> c = -docA.shard.compareTo(docB.shard);
> }
> return c < 0;
> }
> {code}
> The last tie-breaking logic is comparing ShardDoc.shard:
> {code:java}
> // solve tiebreaks by comparing shards (similar to using docid)// smaller 
> docid's beat larger ids, so reverse the natural orderingif (c == 0) {
> c = -docA.shard.compareTo(docB.shard);
> }{code}
>  Here ShardDoc.shard contains node ip as well as shard name, for example: 
> [http://127.0.0.1:8983/solr/my_collection_shard1_replica_n1]
> Consider this setup: 1 collection with 2 shard 2 replica running on a 2 nodes 
> cluster. For the same query, we may have documents coming from the following 
> core combinations:
>  # [http://node1_ip:8983/solr/my_collection_shard1_replica_n1] + 
> [http://node2_ip:8983/solr/my_collection_shard2_replica_n2]
>  # [http://node2_ip:8983/solr/my_collection_shard1_replica_n2] + 
> [http://node1_ip:8983/solr/my_collection_shard2_replica_n1]
> Hence the same request may have different document rankings when there are 
> documents from both shards with the same scores. This can get worse with more 
> nodes/shards/replicas. 
> I'm wondering if we should just use the shard name for tie breaking instead 
> (no node ip), if that's possible



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to