-
Notifications
You must be signed in to change notification settings - Fork 221
RFC for Mango on FDB #407
RFC for Mango on FDB #407
Conversation
rfcs/006-mango-fdb.md
Outdated
| \x50 Array | ||
| \x60 Objects | ||
|
|
||
| An example for a number key would be (\x30, 1). Just too note, Null and Boolean values won’t need to be composite keys as the type key is the value. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/too note/to note
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
or simply Note: Null and Boolean...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. I updated it.
rfcs/006-mango-fdb.md
Outdated
| This design has certain defined limits for it to work correctly: | ||
|
|
||
| * The index definition (name, fields and partial_filter_selector) cannot exceed 100 KB FDB value limit | ||
| * The sorted keys for an index cannot exceed the 10 KB key limit |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"sorted keys" - is this the same as the keys emitted for indexing records?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct. They are.
rfcs/006-mango-fdb.md
Outdated
|
|
||
| ## Terminology | ||
|
|
||
| `Sequence`: a 13 byte value formed by combining the current `Incarnation` of the database and the `Versionstamp` of the transaction. Sequences are monotonically increasing even when a database is relocated across FoundationDB clusters. See (RFC002)[LINK TBD] for a full explanation. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You will probably be using the tuple encoding for the keys, and the Incarnation will therefore be a variable length integer that will be one byte the vast majority of the time (under values of 249 I believe), but will not be strictly speaking 13 bytes. And if you don't use the tuple encoding, I would worry about the potential limiting factor of only one byte. You may find yourself moving databases back and forth across clusters with some regularity depending on how you choose to deploy and load balance logical databases across physical FDB clusters.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @ryanworl, yes the incarnation will be a single byte. I just copied and pasted that section from here https://github.com/apache/couchdb-documentation/pull/397/files#diff-5a51b92701c50f4d70a06d3a85daf8e9R40, maybe I should be a little more explicit in what I mean there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would recommend not making it a fixed-length byte string of length one and instead use an integer. It takes three additional bytes to encode it as a fixed-length byte string in the tuple encoding if the Incarnation is zero and two additional bytes otherwise.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah thanks @ryanworl, I'll mention that in the other RFC.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ryanworl the motivation behind the use of a fixed-length byte string was to ensure the sortability of Sequences in their external hexadecimal string representation in CouchDB's HTTP API. @davisp reminded me that the variable-length integer encoding in the tuple layer does generate bytes that always sort correctly (of course), so I can see where this is a good improvement. Thanks for pointing it out.
rfcs/006-mango-fdb.md
Outdated
|
|
||
| * The index definition (name, fields and partial_filter_selector) cannot exceed 100 KB FDB value limit | ||
| * The sorted keys for an index cannot exceed the 10 KB key limit | ||
| * To be able to update the index in the transaction that a document is updated in, there will have to be a limit on number of Mango indexes for a database so that the transaction stays within the 10MB transaction limit. This limit is still TBD based on testing. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rfcs/006-mango-fdb.md
Outdated
| 3. At the same time a background process will start reading sections of the changes feed and building the index, this background process will keep processing the changes read until it reaches the sequence number that the index was saved at. Once it reaches that point, the index is up to date and `build_status` will be marked as `active` and the index will be used to service queries. | ||
| 4. There are some subtle behaviour around step 3 that is worth mentioning. The background process will have the 5 second transaction limit, so it will process smaller parts of the changes feed. Which means that it won’t have one consistent view of the changes feed throughout the index building process. This will lead to a conflict situation when the background process transaction is adding a document to the index while at the same time a write request has a transaction that is updating the same document. There are two possible outcomes to this, if the background process wins, the write request will get a conflict. At that point the write request will try to process the document again, read the old values for that document, remove them from the index and add the new values to the index. If the write request wins, and the background process gets a conflict, then the background process can try again, the document would have been removed from its old position in the changes feed and moved to the later position, so the background process won’t see the document and will then move on to the next one. | ||
| 5. An index progress tracker will also be added. This will use `doc_count` for the database, and then have a counter value that the background workers can increment with the number of documents it updated for each batch update. It would also be updated on write requests while the index is in building mode. | ||
| 6. Some thing to explore is splitting the building of the index across multiple worker, it should be possible to use the [`get_boundary_keys` ](https://apple.github.io/foundationdb/api-python.html?highlight=boundary_keys#fdb.locality.fdb.locality.get_boundary_keys) api call on the changes feed to get the full list of changes feed keys grouped by partition boundaries and then split that by workers. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| 6. Some thing to explore is splitting the building of the index across multiple worker, it should be possible to use the [`get_boundary_keys` ](https://apple.github.io/foundationdb/api-python.html?highlight=boundary_keys#fdb.locality.fdb.locality.get_boundary_keys) api call on the changes feed to get the full list of changes feed keys grouped by partition boundaries and then split that by workers. | |
| 6. Something to explore is splitting the building of the index across multiple worker, it should be possible to use the [`get_boundary_keys` ](https://apple.github.io/foundationdb/api-python.html?highlight=boundary_keys#fdb.locality.fdb.locality.get_boundary_keys) api call on the changes feed to get the full list of changes feed keys grouped by partition boundaries and then split that by workers. |
| }, | ||
| partial_filter_selector {} - optional filter to process documents before adding to the index | ||
| } | ||
| ``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Format trick:
{
name: "view-name" // optional will be auto-generated
index: {
fields: ["fieldA", "fieldB"] // fields to be indexed
},
partial_filter_selector: {} // optional filter to process documents before adding to the index
}
rfcs/006-mango-fdb.md
Outdated
|
|
||
| 1. When a user defines a new index on an existing database, save the index definition along with the `sequence` the index was added at and set the `build_status` to `building` so it won’t be used to service queries. | ||
| 2. Any write requests (document updates) after that must read the new index definition and update the index. When updating the new index, the index writers should assume that previous versions of the document have already been indexed. | ||
| 3. At the same time a background process will start reading sections of the changes feed and building the index, this background process will keep processing the changes read until it reaches the sequence number that the index was saved at. Once it reaches that point, the index is up to date and `build_status` will be marked as `active` and the index will be used to service queries. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
revisiting: @garrensmith this background process will now likely be a couch_jobs processs right??
rfcs/006-mango-fdb.md
Outdated
| When an index is created on an existing database, the index will need to be built for all existing documents in the database. The process for building a new index would be: | ||
|
|
||
| 1. When a user defines a new index on an existing database, save the index definition along with the `sequence` the index was added at and set the `build_status` to `building` so it won’t be used to service queries. | ||
| 2. Any write requests (document updates) after that must read the new index definition and update the index. When updating the new index, the index writers should assume that previous versions of the document have already been indexed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you elaborate to this? Say you have a transaction that does a write/update. In that same transaction, I'm assuming you want the index to incorporate this new write/update. What do you mean by "read the new index definition"?
9e80aed to
5a78a6a
Compare
jaydoane
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Found just a few nits that could be addressed
|
|
||
| This document details the data model for storing Mango indexes. The basic model is that we would have a namespace for storing defined indexes and then a dedicated namespace per index for the key/values for a given index. Indexes will be updated in the transaction that a document is written to FoundationDB. When an index is created on an existing database, a background task will build the index up to the Sequence that the index was created at. | ||
| This document details the data model for storing Mango indexes. Indexes will be updated in the transaction that a document is written to FoundationDB. When an index is created on an existing database, a background task will build the index up to the Sequence that the index was created at. | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe "... up to the Sequence when the index was created" instead?
rfcs/006-mango-fdb.md
Outdated
| # Detailed Description | ||
|
|
||
| Mango is a declarative JSON querying syntax that allows a user to retrieve documents based on a given selector. It supports defining indexes for queries which will improve query performance. In CouchDB 2.x Mango is a query layer built on top of Map/Reduce indexes. Each Mango query follows a two step process, first a subset of the selector is converted into a map query to be used with a predefined index or falling back to `_all_docs` if no indexes are available. Each document retrieved from the index is then matched against the query selector. | ||
| Mango is a declarative JSON querying syntax that allows a user to retrieve documents based on a selector. Indexes can be defined to improve query performance. In CouchDB 2.x Mango is a query layer built on top of Map/Reduce indexes. Each Mango query follows a two-step process, first a subset of the selector is converted into a map query to be used with a predefined index or falling back to `_all_docs` if no indexes are available. Each document retrieved from the index is then matched against the full query selector. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"In CouchDB 2.x Mango..." isn't it actually: "In CouchDB < 4.0 Mango..."?
rfcs/006-mango-fdb.md
Outdated
| \x40 Text converted into a sort string | ||
| \x50 Array | ||
| \x60 Objects | ||
| In CouchDB 2.x ICU collation is used to sort string key’s when added to the index’s b-tree. The current way of using ICU string collation won’t work with FoundationDB. To resolve this strings will be converted to an ICU sort string before being stored in FDB. This is an extra performance overhead but will only be done when one when writing a key into the index. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
only be done when one when writing a key into the index.
typo
rfcs/006-mango-fdb.md
Outdated
| 1. When a user defines a new index on an existing database, save the index definition along with the `sequence` the index was added at and set the `build_status` to `building` so it won’t be used to service queries. | ||
| 2. Any write requests (document updates) after the saved index definition will update the index with the document update. Index writers should assume that previous versions of the document have already been indexed. | ||
| 3. At the same time a background process via `couch_jobs` will start reading sections of the changes feed and building the index, this background process will keep processing the changes read until it reaches the sequence number that the index was saved at. Once it reaches that point, the index is up to date and `build_status` will be marked as `active` and the index can be used to service queries. | ||
| 4. There is some subtle behavior around step 3 that is worth mentioning. The background process will have the 5-second transaction limit, so it will process smaller parts of the changes feed. Which means that it won’t have one consistent view of the changes feed throughout the index building process. This will lead to a conflict situation when the background process transaction is adding a document to the index while at the same time a write request has a transaction that is updating the same document. There are two possible outcomes to this, if the background process wins, the write request will get a conflict. At that point the write request will try to process the document again, read the old values for that document, remove them from the index and add the new values to the index. If the write request wins, and the background process gets a conflict, then the background process can try again, the document would have been removed from its old position in the changes feed and moved to the later position, so the background process won’t see the document and will then move on to the next one. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will lead to a conflict situation
Is this a conflict or a race? Maybe both?
5a78a6a to
61803f7
Compare
61803f7 to
672d6dd
Compare
|
I've updated this mango RFC so it is up to date with how it is currently implemented. |
|
@garrensmith You have approval from Jay; please merge this. |
RFC for Mango indexes on FoundationDB