 Thank you. Well, first of all, thank you for coming here. I know this is weird to speak about something called MongoDB on this conference, but it's not only MongoDB. So let's see if we can talk about something else. You'll probably know by the title, and this is the reason you have come here. So before starting with TorDB itself, let's do a quick demo, right? Let's see what Mongo looks like and what we can learn from it. So let's try to, yeah, basically I'm going to stop this for a while. I can manage to do it. Yeah, okay. I guess you can read the font size there, right? Okay. So with MongoDB, we can basically fire a Mongo shell. I don't know if you're familiar with this. And you can, for example, try to insert a document like this, for example, or you can try to insert a different document. I'm not going to type it. That's why I have in the history. Like this other one, and then you can try to find the documents you have in your collection. This is basically how MongoDB works, right? Now, the interesting point here is that after we have inserted this document into MongoDB, we can basically go back to the shell and try to find how this MongoDB is running. And it's not running. So there's no MongoDB here. There's got to be something else. And sure, of course, it is something which is called not MongoDB. Let's give it a hand and let's run this all the MongoDB command, which is built info, which returns at the, which version we're running MongoDB. And, well, maybe you can read it better right now. It is, again, it is not MongoDB. So it's totalDB. And this is the topic about this talk. It is something that works as a MongoDB server. And it is absolutely compatible, as you have seen. We were using MongoDB 3.0 command line client zero modifications. But it behaves in a different way. And surprisingly, or non-surprisingly, it uses PostgreSQL. Okay. So let's start this again. Oh, okay. It's just started. So, mm-hmm. Let's really start the game. Damn. Supposedly this should be running. Oh, okay. Seems to be here. Or not. My demo worked better than the presentation. Let's give it a try. Oh, okay. Now I can't go yet. All right. So this was the demo, very quick demo. Now, let's, let me introduce myself a little bit. So I work for a company called 8Kdata. You can try to guess what is, why is this name. That's an exercise. We do basically a lot of research and development in the database space, but we are strongly focused on Postgres, which we have been using for quite a long time. We also do some consulting and training. And we're also the founders of PostgreSQL user group in Spain, which is, it has become a little bit more than a year, the third largest Postgres user group in the world, just after New York and San Francisco. They're way behind, way, you know, in front of us. But anyway, and you know, there you have my Twitter account and my LinkedIn. If you want to connect with me, there's also a Twitter account for dotadb, which is NoSQL on SQL. So let's get started with dotadb. You have seen already it working. So this is no, no fat. It is something real. But it is it in one slide. It is a NoSQL database, JSON oriented, document oriented database. It's open source. It runs on Postgres. It is AGPL licensed. And it has MongoDB protocol compatibility. So it's not a fork of MongoDB. We're just sitting on top of it and implementing the MongoDB wire protocol. Now some of you and some saying it uses Postgres SQL as storage back end. So we're storing things in Postgres SQL. And we know all the advantages that come with doing this, right? Why do we do this? Well, from a technical perspective, what we saw is that most NoSQL databases, if not all of them, which have been, you know, popping up a lot lately in the last years, they have all started from scratch. And doing a database from scratch is something really difficult. I wouldn't do it myself. So concurrency, journaling, durability, transactions, there are sort of really hard things to do and then to get them right. Postgres SQL, general relational databases, but specifically Postgres SQL have been doing this for a while, a real while, 30 years, for years. And it's a shame basically to throw this all to the trash, you know, and start from scratch. Maybe funny, but that's it. It's not very practical, in our opinion. So we prefer, let's start with Postgres and build on top of it. It's reliable, it's flexible, it's proven. That is really important, it is proven. And, you know, we started with Postgres. Now, next question is usually, okay, you're using JSONB. And well, JSONB is absolutely cool. It is very flexible, it works very well. It is really high performance, it is something incredible. However, for our purposes, JSONB is not enough. We need something else. First of all, there's no updates. And we need to update documents without reading them all and rewriting them back to the server. This is going to come soon, I guess. But, you know, anyway, we need it now. Plus, there's a lot involved with MongoDB API related to the query that is quite complex and we needed something more flexible than what JSONB offers. Plus, we are doing some new things that MongoDB is probably not doing. And they cannot basically be done with JSONB, which is basically schema repetition. We are saving a lot of disk space by avoiding all the schema repetition. We're going to talk about this a little bit later. So, if we're not using JSONB, how are we storing things inside .db? Well, we're using a relational database. So, it would be very simple to just have a two column table with the ID and, you know, JSONB or byte A or whatever. That's exactly what some other people have done before trying to emulate what we're doing in .db. But that's not what we wanted to do. So, we wanted to leverage the idea that we have a relational database. So, let's go relation and that's what we do. So, how will we do we store things in .db? We store things in tables. There's no JSONB, there's no binary stuff, no blobs. It's all tables, pure tables. What we do is when we're receiving a JSON document, we split this JSON document into what we call sub-document. Each sub-document, it is one level depth structure. So, no nested things. When there is an object which is nested within a given sub-document, we basically store a placeholder or a pointer to it. And then every sub-document, which is already only one level depth, we store it on a separate table. We analyze the effective type of that sub-document. So, imagine you have a sub-document with names, surname and age. That will probably require a table with text, text, integer. So, we locate a table which is text, text, integer and we store the data there. If that table doesn't exist, it doesn't matter. We will create the table automatically. After all, creating tables in Postgres is very, this is very fast. We've done this in the past where we did a project where we were creating 15,000 tables per second. So, it's not a big deal. Yeah, that is a good point. It's both. So, tables, the name of the columns match exactly the name of the attributes of that sub-document and also the type. So, if you change the name, we will create a new table too. This is better seen with an example. So, there is a final piece on how to glue this all together, which is what we call the structure, the document structure. The document structure is basically the document without data. The keys and the containers, in other words, the arrays and the nested objects. That is the structure. So, it's very short documents, even though for very large GAs and complex documents. And this is what it helps us to glue all together. So, answering your question, the keys are mapped exactly to attributes in the tables and if we need so, tables are created dynamically. Let's look at examples. It's going to be easier. So, imagine, for example, this document. Here we have three levels, right? I don't know if you can see it. No. Right. There's one level which contains basically here name, data and nested. That is the first level. There's another level which contains A and B. And then there's another one which also contains J and deeper and deeper has another level which contains A and B again. So, what we do first with this document is to split into sub-documents, as I was saying, each one containing just one level of depth, which would look like something like this. Name, with data and nested, which are placeholders to the real objects. A and B, A and B at the bottom, and then J42 and deeper with another placeholder for this deeper. Placeholders do not require storage for us. So, we will be basically storing in one table which contains name, which will be a string. So, we'll need one table with an attribute called name with a string. Another table with A, which will be an integer or an America or whatever, and B, a text. And another one with an integer column called J. That's it, because the fourth one will fit on the same table as the second one. And this is very important. We're factoring out all the metadata. So, if we look internally how this is effectively stored in TorDB, it looks like, as I was saying, plus that MongoDB contains an internal attribute, which is called underscore ID, which is a 12 byte random string or so random string. So, the first table contains the name, which belongs here to the first sub-document and the underscore ID, plus two internal columns, which we require in TorDB, which are all at the DID, which is the document ID and the index. I'll explain later what they mean. The next table, table demo T underscore 1, basically contains the structure for storing here the second and the fourth sub-document, because they contain a column A, which is a number or integer, and B, which is a string. And then the third sub-document here, this is J42, is stored on the last table, which only contains a field called J. Now, there's another table, which is structures, which is, as I was saying, basically the document type, the effective document type, and it's very easy to read. It's basically, this is the JSON document. This looks like the original JSON document. And then the main level, it is on table number three. Then there's a nested object called data, which contains each data is sitting on table number one. And then there's another one, which is called nested, which contains its main data is on table number two, and contains a nest object called deeper, where it's information, it's contained on table number one, indexed by index number one, two. So this is basically used, this index field is used to distinguish which entry on a same document, which are on the same table belongs in which place of the placeholder. So basically with these three tables, plus the structure, we're able to glue the document together and recover all the information that we had before. Then we're also now that we're in the relational space, we can also share or repeat the structure. Imagine that someone inserts another document, which share exactly the same structure, the same attribute types, the same names. So why don't we use this structure? And that's what we do in a normal relation table. So we have final table, which is called root, which basically identifies documents for their document ID, this case, zero, with a structure that you're using. So the structure can be reused for several documents. Now, why do we go through all this seems like painful exercise of splitting and putting placeholders and storing tables and creating dynamic tables and so on. Well, first of all, because we were inspired by a previous talk by Christophe Petus, which basically show that storing things in a relational way is could be even orders of magnitude cheaper than storing them in a JSON way, because there's a lot of metadata repetition. I want to show that to you later. So by doing it in this way, we're factoring the structure, we're factoring all the key repetition. And we're storing things in a very efficient way, which can be used later on to do some cool things like imagine you want to query in a pure SQL way, table T one, the one in the middle here, or you want to update a field there. So you could say update demo T one set a equals to a plus one. This is a very cheap operation in SQL, whereas it would be a very expensive or compare comparatively at least a very expensive operation in MongoDB or even in JSONB. And we did some benchmarks. And basically what we were able to find is that to store the same information as compared to MongoDB, we required only 68% down to 29% of the same disk space to store the same data, which is pretty good. Plus, if you think, you know, storage is cheap, that is true. But IO is not cheap. So if you have to read more, then you need to pay more IO, and that is not cheap. So this is very interesting. Yeah, more storage than plain text or than us. Yes. Oh, well, the reality is it is not. Because, well, first of all, what we're doing here, we're not repeating all the time all the keys, because we're factoring them in the definition of the table. Whereas MongoDB, every document is repeating the same and same and same keys. Right? So if you insert a million documents with name surname and age, that strings, name, surname and age are repeated all the time. That wastes a lot of disk space, which we are saving. Plus, the internal representation that MongoDB uses is very verbose in terms of disk space. It's called BSON. It is a serialization of JSON, and it's very inefficient. We're going to sell some examples of how those collections look like. It will probably help you understand why this happens. But this is, yeah, this is basically the idea. And it can get worse or better than this. All right. A little bit about the software. How this is built. So, third DB is written in Java. Sorry about that. But it works for us. It has been designed in the purpose to work with Java 6 so it can be deployed in corporate environments where are still stuck in Java 6 or those who are previously in Java 6. I'm sorry. It's been tested in basically the Oracle VM and the OpenJDK, of course. But there's also another high-performance JVM. It's called the ASL JVM, which is great and is postless JVM, which will probably bring some benefits on top of it. And it's currently deployed as standalone application, a JAR file. So, basically, download third DB, third DB, get the JAR file, run Java as JAR and you're ready to go. Now, complex installation process. But it can also, it's going to be also published as an ER file, which basically means that you can drop that file into your favorite application server and it will run. It is very good because a lot of companies have standardized on the process of deploying something on application servers. So, it will be completely a standard process for deploying this on a corporate environment. We're not alone. I mean, as I was saying before, we are not able to build big things without relying at least on some other things that are really big. So, we're relying on millions of lines of code, really the very smart people that we are building upon. Like, well, postless, of course. But also Netty, which is a network IO framework which provides us event-driven asynchronous high-performance networking. It's very easy to implement the protocol on top of Netty. The Hickory connection pooler, which is probably the best Java connection pooler we have ever seen. Standard tools in Java that makes your life easier, like WAVA, Jue's, FindBags. Juke is a great, great tool for acquiring database, like Postgres from Java. So, we're building this well-proven, well-tested software. So, software is probably better. Thanks for this. Our codebase is very modular. We are excessively modular in our design. We try to use every modular, every layer that we can. And we have to build some layers which are very interesting on their own. Like, for example, what we call the D2R. D2R is the layer that transforms in a representant, representation independent manner from documents to relational. So, now we're speaking MongoDB protocol. In the future, we may speak a different protocol and convert from that protocol to relational. We also have internal representation of what is the document which is called QV document, which is, again, representation independent layer of a document. And we also have an abstraction layer over the database. So, we can plug in different backhands. We're going to show some experiments later. Well, this is probably only interesting for Java developers, but this is what it looks like, the module instructor. Let's skip this. But there's another important layer which we're building upon, which is called MongoWP. This is MongoWP protocol. And this is a layer to basically help developers that want to create server-side type or middle-word type applications which speak the MongoDB protocol. Like, towardDB. That's why towardDB is built on top of this library. It is a very simple to use library. It offers a simple callback interface where everything is parsed for you. So, if you do an insert, this layer will decode the insert in an event-driven, asynchronous nature, provide you a callback with all the message decoded and an object to basically issue a reply. You don't need to understand the protocol, not even a single bit. So, it's very convenient. And it's also very modular. It's based on NetE and, you know, can be used for developing in the future all the tools like proxies, query routers, transparent loggers, whatever for the MongoDB protocol. It can also be extended for other protocols. But this is what it is right now. It's very modular. Let's skip this. So, now we have built is something which relies on Postgres to implement Mongo features, right? And we implemented Mongo protocol and I've shown you how it saves this space. But that wasn't enough. We wanted to go further. We were relying on Postgres. And Postgres, you know, perfectly well what it offers. So, why don't offering, basing our code on things that Postgres does, try to offer things that Mongo can do simple. So, we want a little bit beyond or that's what we're trying to do. For example, we have addressed five possible pain points for MongoDB users. We're going to go one by one. The first one is what we call the schema less fallacy. So, no SQL databases are schema less, right? Well, no. There's no schema less thing. It's more dynamic scheme or something like that. But the schema, it is effectively attached to the data. So, look at this example. It is a fallacy. Well, first of all because I'm not that tall, right? But other than that, if you look at this document and really analyze it, the things that are highlighting in blue, there is schema. The attribute names, the start of a container, not an array, a container, that bracket, that's also schema, that marks a structure. Isn't that what we really call metadata and isn't metadata schema? So, there's a schema here, right? If we look at the internal representation of MongoDB, the business realization I was referring to before, it's even worse because this is how it looks like once it's been stored into MongoDB. So, there's a schema on the attribute name, but then there's also schema specifying the type. It is typed representation. And there's also schema like, for example, the containers, the supposedly arrays, internally they are represented like nested objects where the keys are zero, one, two, three, whatever. So, there's a lot of schema here. And as you can guess, if you insert a lot of documents with the same look like, right, you're repeating a lot of this schema all the time. That's why we're saving a lot of this space. So, these things are not schema-less. And that's why we call it attach the schema, where the schema is attached to the data. You know, we've seen what benefits we have from factoring this out into tables. Now, going beyond this, if you think how basically an engine like MongoDB stores documents, they are serialized to this representation and put one after the other one. So, if you insert different document types in one after the other, they will be stored again, one after the other. So, they will be kind of mixed. So, if you really insert documents and look, analyze how they look like internally, they may look something like this. Right? You know, there are many persons mixed with cars, mixed with payments, mixed with, I don't know, you know, all types are one going after the other. But as I was saying, there's a lot of repetition. In a normal exercise, if you insert millions of documents of typical real use case collections, you find something like this, that effective types are repeated. Types here with the same color are being repeated. So, we did some tests and we find out that even in the worst case, you won't find more than thousands of documents, different document types, when I give in collection, even with millions of documents. There's called some degraded cases, but they're not useful. And we know that creating tables in Postgres is not big deal. First of all, I mentioned before, it was fast. We also know, because we also did an experiment some years ago, that we can create a large number of tables in Postgres. We tried creating two billion tables in Postgres and it worked quite well. So, it's not big deal. Plus, we've seen thousands in the worst case for real cases scenarios, right? So, this is how things are stored in a JSON or, yeah, JSON data store like MongoDB and more or less this is how we're storing them. So, apart from saving dusk and saving IO consequently, what we're doing is that we are classifying effectively the data. It's like if we were partitioning data by type. So, we can do something which is what we call query by structure or query by type is that we have remember that structure stable that we had was the way for us to merging the document back together? Well, we can use that for doing this query by partition because just only by looking at that table if you remember it is something it was here this structure table on top just by looking at this table which has a low cardinality thousands in the worst case as I was saying before. We can find out whether your document your query will match one or more structures like imagine you're looking for a query which contains deeper. Well, we can look here and figure out which documents exactly have that column without looking at the real data. So, we only need to look here to guess which tables to query. So, rather than scanning the whole database which is the only way apart from indexed columns that you can do in a no SQL data store we only need to query a subset of the data. Yeah, current implementation is using JSONV for this document but it's you know we're using barely I mean this document is small cardinality is not very big and we're using basic operations on top of that JSON operations. We were thinking about even adding compatibility for 9.2 by using JSON rather than JSONV and that's something we can do. Right, so we're querying by type. We're scanning only a subset of the data needed to address the query and that gives us the possibility of you know looking only a subset of the database to address a query. There is an even a potential use case for this very interesting what is what we call the negative queries. If you're querying for something that doesn't exist well on MongoDB for example or any other no SQL data store you will have to scan the whole database so if it's a petabyte database you'll have to scan petabyte of data just to find out that there's the answer is an empty set whereas here we'll look at the queries at the structure table which is usually very small and will say no the answer is the empty set. That table is so small that we're caching it memory so we will answer from memory. It can be technically speaking infinitely faster for negative queries. I don't do benchmarks that that because I could put the number I want. What else? Well single node durability. This is very simple. Postgres durability is cheap. It has been done, has been tested for so many years. MongoDB it is not that simple. The only way to achieve true single node durability in MongoDB is using a parameter to the insertions or to the updates called JTRU which basically weights database performs a journaling and then adds things to the desk but this operation is not as optimized as it is in Postgres so it's very expensive in other way. I bet there are no benchmarks out there where they're claiming the speed of MongoDB that are using JTRU. They're not using JTRU otherwise the speed drops significantly. So it is not very cheap whereas for us it is very cheap or it's what it is but definitely it is something way more optimized than you can find on MongoDB. Plus we can enforce this. In MongoDB you cannot enforce this. It is a responsibility of the user of the application whether to send JTRU or not. So there's no way to enforce strict durability on single node. Clean reads. So this is a very interesting topic. If you go into the internet and you Google or search for whether MongoDB has or not suffers from dirty reads you will end up concluding that the answer is no. So you can see here there is no dirty reads in MongoDB. Oh really? So let's look at MongoDB documentation. Basically if you read that the official documentation updated for version 3.0 it says MongoDB will allow clients to read the results of a write operation before the write operation returns. Damn that sounds like dirty reads doesn't it? If the MongoDB terminates before the urinal commits queries may have read data that will not exist after MongoDB restarts. Hmm that doesn't seem like very clean right? And well the thing is that they claim they are not dirty reads because if you look at the definition dirty reads involve uncommitted data and they don't have transactions they don't have commits. So you cannot claim that they are dirty reads because it's not uncommitted data. They are always committing data right? But that's definitely not clean reads. So we decided to call these tainted reads. Now if you dive deeper there is a parameter called a snapshot. Oh snapshot. So if I use your query under snapshot mode that's going to be clean right? Nope. The snapshot does not warranty that the data returned by the query will reflect a single moment in time. Okay enough. So it's not. Basically what a snapshot does is that it prevents you from having a document returned twice while in the process of your query. Thank God. Now in Postgres this is very easy. We have transaction isolation modes and for us is enough to issue queries on repeatable read mode. Read committed is not enough because Mongo protocol allows a query to be run under different roundtrips to the server which can have no state. So we need to open when MongoDB opens a Courser we open an equivalent Courser in TorDB in Postgres right? Which lasts for a while right? And we open that Courser in repeatable read mode and thus we get consistent reads. So again this is something which is provided for us by the grace of Postgres and give us really true clean reads even the protocol being stateless. Atomic operations. Okay this one is very easy right? We have transactions in Postgres so all we can make all the operations you know all or none at once. MongoDB has a harder time here. They have even a flag which is called isolated which basically means they take a big lock and do only one write during that operation. But even then that is not atomic. It prevents insertions or updates to be interleaved with all the operations happening concurrently because they don't happen concurrently. There's a big lock exclusive lock there. However a single insert or one of them may fail. So when people are programming with MongoDB they should they don't do it but they should be checking every document whether it was finally inserted or updated or not. Well in ToriDB that's not a problem because we can run in a transaction. Indeed everything is run under a transaction so it's just basically we can offer atomic semantics in ToriDB. Indeed we don't offer them by default. I mean it's offered by default you can change it by using a parameter which is called continue and error and in that case we will do a transaction per document which will be slower. So basically if you want to emulate MongoDB behavior by default we will be slower. But we can do it. It's all about flexibility. What else? Hacking currency. Postgres is highly concurrent, works extremely well and MVCC is absolutely great for currency. MongoDB it's not that concurrent at least not until version 3.0. Under previous versions or with the current storage backend was called MMAP they basically take an exclusive lock and the new war tigers document locked but again it's hard to match concurrent behavior of MVCC in Postgres so we get better concurrency again for free. What else? We just state this ToriDB currently it is still in developer preview. We are trying to follow a release early release often policy so we're encouraging you to give it a try download and submit bugs issues send us feedback it is still there's a way to go I'm sure maybe things will still break but please give us feedback send bags go to github all the source code is publicly available and we really appreciate any comment or help that may come from you. How to use it as I mentioned before is very simple yes either build the source code yourself with Maven or download the JAR file and do Java does JAR the ToriDB JAR file and specify the database username and port in which you want to run the software that's it there are a couple of command lines more available but this is basically the way to use it very simple. What's been the response? Well so far the community response has been overwhelming it's been great there's a lot of interest especially in the no SQL communities to about ToriDB. We made fortunately front page to Hacker News given day and gave a lot of you know stars and github we're trending repo number two on that day it's only behind a project by Facebook which was about SQL damn if you read the tweets this is very funny this is not necessarily my opinion but you know there's people saying basically loving look of ToriDB it speaks the Mongo protocol and Postgres relational backend best of both speaks natively the MongoDB protocol and saves your data why not ToriDB it's like Mongo but it's not built on a platform of fail there are some other comments which is like you know as nice as SQL storage and you start these days project like ToriDB speak to a real problem SQL is a fucking terrible API okay you know it's been very interesting there's a great feedback and we're very happy with it so what is the roadmap where are we at so I was saying before this is currently developer PV mode we expect version 1.0 to come around to go out around Q4 this year we're trying to get it out quick soon it will be production ready it will implement a large subset of the MongoDB protocol basically all that is usually used not crazy things and it will also include the MongoDB replication protocol so you could replicate from from MongoDB into ToriDB plus maybe some other stuff what are our priorities in terms of development well priority number one for us is to be able to offer MongoDB API on top of what is current infrastructure for most companies most places there's relational database rather than no SQL database rather than MongoDB database so we want to address that so we want them to make it easy to offer for whatever reason MongoDB APIs to their developers and then offer on top of that many features that I've been talking about today that are not currently offered or offered in a different way by options like like MongoDB and finally performance performance is very important for us but it's not number one priority at least now however performances I would say it's really good there's a lot of benchmarking to do and you're again this open searcher welcome to contribute this benchmarking and submit the results we'll be happy to see them in but I can tell you it is it is really good so far but we want to make it better and finally and as a final address for this talk I want to show you a couple of things we're doing in a highly experimental fashion to go even beyond that we would be I've been presenting today first of all we try to use columnar storage using the C store plugin from our extension by C2 data and we also want to try to use as long as we have an abstraction to the for the back end we want to use Postgres Excel as a likely back end for .db so this will require a little bit of of extra code basically having a distributed cache because we're caching some information this will need to be distributed but it can be done somehow easily and finally try it with pg-start for doing charting in .db I want to talk a little bit about the first one so remember those pictures where we were showing how do we store JSON documents right by splitting them into tables which are of uniform type we have basically classified data into columns now if you would like to perform big data types big data loads on top of a but would have been otherwise a no SQL database it's really hard because if you think about doing an aggregation aggregated operation on top of something which you don't know what is a structure you don't know which documents have those columns you have to go document by document parsing them analyzing all them and then performing the you know the aggregated operation whereas in our case as long as we have pre-classified the data you only look at the subset of the data but now if you want to do it like vertically in an aggregated fashion why not use a columnar store now that we have to split things into tables we can now go columnar and we gave it a try to this we haven't analyzed performance but we have analyzed that what is the requirements for storage for doing these things and C store from C2's data allows us to transparently compress information which works very well if the information in that columns is of a similar type so what are the results that we achieved with this basically comparing to MongoDB we required from 20 percent down to 1 percent 1.17 percent of disk space to store the same information this is of course a very synthetic benchmark it wasn't done by us it was a benchmark by EnterpriseDB which was comparing Postgres and MongoDB so we took that same data benchmark that same data something it's a little bit synthetic don't speak don't expect this in production but this is an example of what can be done we're storing in just 50 megabytes a collection of documents which took four and a half gigabytes of this space in MongoDB imagine the potential for this everything is going to be on drum compared to disk so this is basically it I'm welcoming questions now okay the MongoDB protocol basically when you're doing a query there's it is a stateless somehow so you do a query and if we will return by default at most 1,000 results then if you want more you need to do a separate request which is completely independent so there's no notion of a session so you issue another query and say get more results and and then you you will basically get more results from that cursor now in order for us to do that we will keep a transaction open but we can reuse the connection for all the things if we want to and that's what we're doing so basically we place the connection and that we leave the cursor open in repeatable read mode so we can do any operation in between if we wanted but the snapshot is stable yeah but as far as I understand we don't need serializable because the operation doesn't need to be in serial order it is enough that the snapshot is consistent at the start of the transaction and it's read only even if even in read only mode would be good to test anyway but we're in read only mode because you know so there's no no test I mean there's there's no possibility of failure next milestone which will be probably version 0.3 or 0.4 I like 0.4 because it's binary we'll we'll address this issue and we will implement the functionality of replicating the basically the client part of the protocol so you'll be able to replicate from MongoDB to TorDB I guess that will help in that direction yeah yeah I mean the the features that may have they have announced in 3.0 are basically that now the storage and the storage is pluggable so you can plug in your storage engines and they have they're offering to the previous one which has of course sorry a finer right now locks locking and a new one which is called wiretiger wiretiger seems to be way better than what it was before and it's more concurrent too but I don't know if it's let's say production ready right wiretiger also offers optional compression and with the compression they save a lot of disk space but of course that compression is not free it requires CPU cycles yeah okay this is a very common thing you do an update and one key disappears and not one pops up right in that case we'll migrate that part of the document to a different table so we never do outer table tables are table structures are immutable either you have a table that fits your data and you will put it there or you will create a new one sorry where is it now we've seen that we can have two billion tables on a Postgres database no no no need to I know could be done in yes yeah yeah on with with that number of tables slash dt takes forever literally but I don't intend this to be used by a from pg admin although you may do it all right is that it okay thank you very much for for camera