Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get Firestore Index Merge to work?

I am having trouble using firestore index merging in order to reduce the number of required indices.

Consider this example situation:

Firestore Collection: test/somedoc

{
  a: '1',
  b: '1',
  c: '1',
  d: '1'
}

This will cause Firestore to create 4 automatic single field indices on test for fields a to d.

Querying this table with a few equality conditions and one unrelated sort:

    await db.collection('test')
        .where('a', '==', '1')
        .where('b', '==', '1')
        .where('c', '==', '1')
        .orderBy('d')
        .get();

This causes Firebase to fail with a prompt for a composite index creation with all fields included. This is expected.

Now according to the docs (https://firebase.google.com/docs/firestore/query-data/index-overview#taking_advantage_of_index_merging), if you already have a composite on e.g. fields c and d, firestore will use index merging instead of requiring a composite index on all fields.

firestore-index

However if you create an index on collection test e.g. with c asc, d asc, the query will still fail with prompting to create the full composite index.

UnhandledPromiseRejectionWarning: FirebaseError: The query requires an index. 

What am I doing wrong here?

like image 402
Aurangzeb Avatar asked Dec 11 '20 05:12

Aurangzeb


People also ask

What file should be used for firestore indexes firestore indexes JSON?

From the CLI, edit your index configuration file, with default filename firestore. indexes. json , and deploy using the firebase deploy command.

What is index merging?

The Index Merge access method retrieves rows with multiple range scans and merges their results into one. This access method merges index scans from a single table only, not scans across multiple tables. The merge can produce unions, intersections, or unions-of-intersections of its underlying scans.

How do I export firestore index?

It's possible! Run from CLI firebase firestore:indexes inside your firebase project folder. Providing you have indexes already setup and logged into Firebase via the CLI too, you'll get a formatted JSON output for you to copy. Exported indexes can be re imported using firebase deploy --only firestore:indexes .


Video Answer


2 Answers

Ok finally understood the problem here.

In order to index merge to work, you need composite-indices that cover all related fields. The auto-generated single field indices won't be used for merging.

Consequently, if you create two additional composite indices

  • a asc, d asc
  • b asc, d asc

then all fields will be covered and index merge will be used automatically.

like image 88
Aurangzeb Avatar answered Oct 19 '22 00:10

Aurangzeb


@Aurangzeb has the correct answer but I want to elaborate

So it is true that if you want to use index merging on that query you need 3 composite indexes (a, d), (b, d), and (c, d).

However using a single (a, b, c, d) index will still be faster in some cases and you should consider adding it anyway. Index merging is slower in the case where the result sets from the 3 indexes are of very different sizes. Consider your query:

collection
  .where(a == 1)
  .where(b == 1)
  .where(c == 1)
  .orderBy(d)

Let's say you have a collection of a million documents and 50% of them have a == 1 or b == 1 but only 0.1% of them have c == 1. In this case reading from the (a, d) index is actually doing quite a bit of wasted work before the (c, d) index eliminates most of the results. A single (a, b, c, d) index does the least work possible. This is why the Firebase SDKs and console always suggest the most exact index even if there is a way to satisfy the query with merged indexes.

like image 21
Sam Stern Avatar answered Oct 19 '22 00:10

Sam Stern